# 函数-new
# 实现
function newObj(ctor, ...args) {
let obj = {}; // 1、创建一个空对象
obj.__proto__ = ctor.prototype; // 2、将对象的原型属性链接到构造器的原型实例上,建立原型链
let res = ctor.apply(obj, args); // 3、执行构造器函数
return typeof res === 'object' ? res : obj; // 4、若构造器函数返回的是一个对象,则return这个对象,否则返回第1步中创建的实例
}
1
2
3
4
5
6
7
2
3
4
5
6
7
这里return前要判断构造器是否返回对象的原因是:构造器可能将属性和方法都通过return返回出来,而不是在this上。
看下面的例子:
function newObj(ctor, ...args) {
let obj = {}; // 1、创建一个空对象
obj.__proto__ = ctor.prototype; // 2、将对象的原型属性链接到构造器的原型实例上,建立原型链
ctor.apply(obj, args); // 3、执行构造器函数
return obj; // 4、若构造器函数返回的是一个对象,则return这个对象,否则返回第1步中创建的实例
}
function Person(name, age) {
this.name = name;
this.age = age;
}
let person1 = new Person('Aaron',31); // Person {name: 'Aaron', age: 31}
let person2 = newObj(Person,'Aaron',31); // Person {name: 'Aaron', age: 31}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
上面的例子中,构造器将属性绑定到this上,因此在newObj中创建的obj中,也响应的绑定上了。
再看下面的例子:
function newObj(ctor, ...args) {
let obj = {}; // 1、创建一个空对象
obj.__proto__ = ctor.prototype; // 2、将对象的原型属性链接到构造器的原型实例上,建立原型链
ctor.apply(obj, args); // 3、执行构造器函数
return obj; // 4、若构造器函数返回的是一个对象,则return这个对象,否则返回第1步中创建的实例
}
function Person(name, age) {
let obj = {};
obj.name = name;
obj.age = age;
return obj;
}
let person1 = new Person('Aaron',31); // Person {name: 'Aaron', age: 31}
let person2 = newObj(Person,'Aaron',31); // Person {}
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
上面的例子中,person2返回的是空对象,因为在构造器中属性是绑定在内部对象上,然后通过return返回出来的。为了接受到这个返回,我们需要判断一下,也就是 return typeof res === 'object' ? res : obj
这行代码的意义所在了。
# 加强版(仅供参考)
3个步骤:
- 以ctor.prototype为原型创建一个对象。
- 执行构造函数并将this绑定到新创建的对象上。
- 判断构造函数执行返回的结果是否是引用数据类型,若是则返回构造函数执行的结果,否则返回创建的对象。
function newOperator(ctor, ...args) {
if (typeof ctor !== 'function') {
throw new TypeError('Type Error');
}
const obj = Object.create(ctor.prototype);
const res = ctor.apply(obj, args);
const isObject = typeof res === 'object' && res !== null;
const isFunction = typeof res === 'function';
return isObject || isFunction ? res : obj;
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11