定义
根据MDN
定义:
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象类型之一
举个例子:
function Person (name, age) {
this.name = name;
this.age = age;
this.habit = 'Games';
}
Person.prototype.strength = 60;
Person.prototype.sayYourName = function () {
console.log('I am ' + this.name);
}
var person = new Person('Kevin', '18');
效果:
从这个例子中,我们可以看到新实例 person 可以做到:
- 访问到 Person 构造函数里的属性
- 访问到 Person.prototype 中的属性
因为 new 是关键字,无法直接覆盖,所以我们写一个函数,命名为 fakeNew,来模拟 new 的效果。用的时候是这样的:
function Person () {
……
}
// 使用 new
var person = new Person(……);
// 使用 objectFactory
var person = fakeNew(Person, ……)
手动实现
基本实现
因为 new 的结果是一个新对象,所以在模拟实现的时候,我们也要建立一个新对象,假设这个对象叫 obj,因为 obj 会具有 Person构造函数里的属性,想想经典继承的例子,我们可以使用 Person.apply(obj, arguments)来给 obj 添加新的属性。
//1. 创建一个新对象
//2. 获取Constructor为传入的第一个参数(Constructor必须大写哦)
//3. obj.__proto__实例下为Constructor,prototype
//4. 将Constructor所有属性继承到obj上
//5. 返回这个obj
function fakeNew() {
var obj = new Object(),
Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
Constructor.apply(obj, arguments);
return obj;
};
复制以下的代码,到浏览器中,我们可以做一下测试:
function Person (name, age) {
this.name = name;
this.age = age;
this.habit = 'Games';
}
Person.prototype.strength = 60;
Person.prototype.sayYourName = function () {
console.log('I am ' + this.name);
}
function fakeNew() {
var obj = new Object(),
Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
Constructor.apply(obj, arguments);
return obj;
};
var person = fakeNew(Person, 'Kevin', '18')
效果:
返回值情况实现
上面的实现有一个问题,那就是无法返回有返回值的情况。
接下来我们再来看一种情况,假如构造函数有返回值,举个例子:
function Person (name, age) {
this.strength = 60;
this.age = age;
return {
name: name,
habit: 'Games'
}
}
var person = new Person('Kevin', '18');
console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) // undefined
console.log(person.age) // undefined
这个例子中,构造函数返回了一个对象,但在实例 person 中只能访问返回的对象中的属性。
需要注意的是,在这里我们是返回了一个对象,假如返回一个基本类型呢?
function Person (name, age) {
this.strength = 60;
this.age = age;
return 'handsome boy';
}
var person = new Person('Kevin', '18');
console.log(person.name) // undefined
console.log(person.habit) // undefined
console.log(person.strength) // 60
console.log(person.age) // 18
我们发现这样并不能返回,返回值会被忽略。
所以我们还需要对象进行特殊处理,如果是一个对象,我们就返回这个对象,如果没有,就直接返回。
function fakeNew() {
var obj = new Object(),
Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
var ret = Constructor.apply(obj, arguments);
return typeof ret === 'object' ? ret : obj;
};
测试一下:
这样我们就实现了自己的 new ,YES ~~~
JavaScript基础专题系列
JavaScript基础专题之原型与原型链(一)
JavaScript基础专题之执行上下文和执行栈(二)
JavaScript基础专题之深入执行上下文(三)
JavaScript基础专题之闭包(四)
JavaScript基础专题之参数传递(五)
JavaScript基础专题之手动实现call、apply、bind(六)
JavaScript基础专题之类数组对象(七)
新手写作,如果有错误或者不严谨的地方,请大伙给予指正。如果这片文章对你有所帮助或者有所启发,还请给一个赞,鼓励一下作者,在此谢过。