文章來源於我的個人博客: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的效果!