JavaScript中new的實現

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章