JS中new背后的执行过程
# 执行过程
- 创建一个新的空对象,并将新对象的原型
__proto__
指向构造函数的原型对象prototype
- 将构造函数中的 this 指向新对象
- 执行构造函数中的代码,为这个新对象添加属性和方法
- 判断并返回 (正常就是返回新建的对象)
根据上面执行过程,可以封装如下实例化函数:
// es5
function instantiate (constructor) {
var obj = {}
obj.__proto__ = constructor.prototype
var res = constructor.apply(obj, Array.prototype.slice.call(arguments, 1))
return res instanceof Object ? res : obj
}
// es6
function _instantiate (constructor, ...args) {
const obj = Object.create(constructor.prototype);
const res = constructor.apply(obj, args)
return res instanceof Object ? res : obj
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 返回值
第四步返回值的处理可以简单看成:
- 如果是值类型,就丢弃它,返回新建的对象 (没有return,相当于return undefined,也返回新建的对象)
- 如果是引用类型,就使用 return 的返回值,新建的对象也就没意义了,也就是new操作符无效
更详细的过程请看规范 (opens new window)
function Person(name){
this.name = name;
return 1; // return undefined/NaN/'string'/null
}
const me = new Person('James');
console.log(me); // { name:'James' }
1
2
3
4
5
6
2
3
4
5
6
function Person(name){
this.name = name;
return { age:18 };
}
let me = new Person('James');
console.log(me); // { age:18 }
1
2
3
4
5
6
2
3
4
5
6
# constructor
为了记录「实例对象是由哪个构造函数创建的」,在构造函数的原型 prototype 添加了一个 constructor
属性,并指向构造函数本身。
function fn () {}
console.log(fn.prototype.hasOwnProperty('constructor')) // true
console.log(fn.prototype.constructor === fn) // true
1
2
3
2
3
任意一个新函数在创建时,原型的 constructor
就已经设置好了,并不需要手动去设置它的 constructor
属性,
但是在对 prototype 重新赋值的时候,需要重新指定 constructor
属性,否则将会丢失 constructor
属性。
function Person (name) {
this.name = name
}
Person.prototype = {
constructor: Person,
sing() {
console.log('唱歌')
},
dance() {
console.log('跳舞')
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 演示
function instantiate (constructor) {
var obj = {}
obj.__proto__ = constructor.prototype
var res = constructor.apply(obj, Array.prototype.slice.call(arguments, 1))
return res instanceof Object ? res : obj
}
function Person (name) {
this.name = name;
}
var p1 = new Person('James')
console.log(p1.name)
console.log(p1 instanceof Person)
var p2 = instantiate(Person, 'James')
console.log(p2.name)
console.log(p2 instanceof Person)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
编辑此页 (opens new window)
上次更新: 2023/02/02, 14:58:40