JS模拟new

一、开始

同样我们先来看看 new 操作符为我们做了什么事情:

1
2
3
4
5
6
7
8
9
10
11
12
function Person(name, sex){
this.hobby = 'shopping';
this.name = name;
this.sex = sex;
this.sayName = function(){
console.log(this.name)
};
}
Person.weight = '60kg';
Person.prototype.friend = 'rose';
var person = new Person('jack','age');
person.sayName()

new.png
可以看到原型链的对象被继承下来了,定义在方法外的属性没有被继承下了,返回了一个新对象,可以传递参数

二、实现模拟

我们要做的是,返回一个新对象,把原型链指向构造函数,传递参数

1
2
3
4
5
6
7
8
9
function Create(){
var obj = {};
var Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
Constructor.apply(obj,arguments);
return obj;
};
var person = Create(Person,'jack','age');
person.sayName();

其实很多东西只要是知道了干什么的,再去实现起来就很有思路了

三、显式返回对象

  • 如果构造函数显式返回了一个对象,那么所有的属性都不会被继承了
  • 返回一个数组也一样,因为在 JS 中数组也是由对象构造而来的
  • 但是返回的是 string,number,undefined,null,boolean 等等基本类型就不会了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Person(name, sex){
this.hobby = 'shopping';
this.name = name;
this.sex = sex;
this.sayName = function(){
console.log(this.name)
};
return {
name: 'mike'
}
}
Person.weight = '60kg';
Person.prototype.friend = 'rose';
var person = new Person('jack','age');
person.sayName()

new1.png

  • 可以看到结果就是显式返回的那个对象,所以要再修改以一下 Create 的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
function Create(){
var Constructor = [].shift.call(arguments);
var test = Constructor();
if(test instanceof Object && test !== null){
return test;
}else{
var obj = {};
if(Constructor)
obj.__proto__ = Constructor.prototype;
Constructor.apply(obj,arguments);
return obj;
}
};