# 实现new
考点:
- 构造函数, 原型链
函数通过 new
操作符调用, 此时函数被称为构造函数, 运行后会返回一个对象, 该对象的 __proto__
属性指向构造函数.prototype
function Cat(name) {
this.name = name;
}
Cat.prototype.miao = function () {
console.log("瞄~!");
};
let cat = new Cat("大毛");
console.log(cat.__proto__ == Cat.prototype); // true
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
由于 new
是语言层面的操作符, 所以用函数来模拟 new
的功能:
function newFactory(constructor) {
let obj = Object.create(constructor.prototype)
// 等同于 obj.__proto__ = constructor.prototype
let args = Array.from(arguments).slice(1)
constructor.apply(obj, args)
return obj
}
function Cat(name, color) {
this.name = name;
this.color = color
}
Cat.prototype.miao = function () {
console.log("瞄~!");
};
let cat = newFactory(Cat,"大毛", '橘色');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
改进: 当构造函数本身会返回一个非null的对象时, 则通过 new
会返回这个对象, 其他情况还是会返回新生成的对象
function Cat(name) {
this.name = name
return {
name: 'zs'
}
}
Cat.prototype.miao = function() {
console.log('瞄~!')
}
let cat = new Cat('大毛')
console.log(cat.name) // 'zs'
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
因此需要将调用 cat后返回的结果进行判断, 如果是非null的对象, 则返回该对象, 其他情况返回新生成的对象
function newFactory(constructor) {
let obj = Object.create(constructor.prototype);
// 等同于 obj.__proto__ = constructor.prototype
let args = Array.from(arguments).slice(1);
let result = constructor.apply(obj, args);
return result instanceof Object ? result : obj
}
function Cat(name, color) {
this.name = name;
this.color = color;
return {
name: 'zs'
}
}
Cat.prototype.miao = function () {
console.log("瞄~!");
};
let cat = newFactory(Cat, "大毛", "橘色");
console.log(cat) // {name:'zs'}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21