文章来源于我的个人博客:JS中new的实现
JS中通过new操作符可以创建构造函数的实例对象,我们可以看看以下例子:
function Person(name,age){
this.name = name
this.age = age
console.log(this) /* Person {name: "tanj", age: "18"} */
}
Person.prototype.sex = '女'
var p = new Person('tanj','18')
console.log(p.name,p.age) /* tanj 18 */
console.log(p.sex) /* 女 */
console.log(p.__proto__ === Person.prototype) /* true */
上面的例子中,我们创建了一个Person构造函数,并且通过new创建了一个该构造函数的实例对象p,通过输出打印我们知道通过new操作符:
构造函数内部的this绑定到了实例对象上;
实例对象可以访问构造函数内部的属性与方法;
实例对象可以访问构造函数原型对象上的属性和方法;
实例对象的__proto__属性指向构造函数的原型对象。
现在,我们知道new操作符可以实现上述功能,上面的例子中我们Person构造函数并没有返回值,如果我们给Person设置返回值,那么再通过new会得到怎样的效果呢?看看下面的例子:
function Person(name,age){
this.name = name
this.age = age
}
function Person2(name,age){
this.name = name
this.age = age
return {
'test':'测试一下返回值是对象'
}
}
function Person3(name,age){
this.name = name
this.age = age
return "测试返回值是字符串"
}
var p = new Person('tanj','18')
console.log("new Person('tanj','18')",p)
var p2 = new Person2('tanj','18')
console.log("new Person2('tanj','18')",p2)
var p3 = new Person3('tanj','18')
console.log("new Person3('tanj','18')",p3)
我们给出了三个构造函数,它们的返回值分别是:无返回值、返回对象、返回字符串,输出结果如下:
通过上面的例子我们可以知道,如果构造函数的返回值是对象,那么就返回这个对象,否则,返回new操作为我们创建的对象。
那么,new操作内部到底进行了哪些操作呢?
1)创建一个空对象;
如:var obj = new Object()
2)将这个空对象的__proto__属性指向构造函数的原型对象 ;
如:obj.__proto__ = Person.prototype
3)将构造函数中的this绑定到创建的空对象中,并执行构造函数的代码;
如:Person.call(obj,'tanj','18')
4)如果构造函数的返回值不是对象,那么就返回第一步中创建的对象。
如:return (Person() instanceof Object)?Person():obj
一起来模拟实现new吧!
function myNew(func,...args){
var obj = new Object()
obj.__proto__ = func.prototype
var ret = func.call(obj,...args)
return (ret instanceof Object)?ret:obj
}
再来测试一下效果:
function Person(name,age){
this.name = name
this.age = age
}
function Person2(name,age){
this.name = name
this.age = age
return {
'test':'123'
}
}
function myNew(func,...args){
var obj = new Object()
obj.__proto__ = func.prototype
var ret = func.call(obj,...args)
return (ret instanceof Object)?ret:obj
}
console.log(new Person('tanj','18'))
console.log(myNew(Person,'tanj','18'))
console.log(new Person2('tanj','18'))
console.log(myNew(Person2,'tanj','18'))
看看打印了什么吧!显然,我们已经实现了new的效果!