new操做符到底幹了什麼

以前一直很迷惑new一個函數究竟是個啥,筆記本上處處戳戳,還有不一樣時期的不一樣理解。理解A:new X 是建立一個繼承X.prototype的對象。理解B:使用new調用一個函數,將會構造函數的做用域付給新對象:a = new B()把B的this給a。????????????我記的啥,怎麼看起來那麼迷惑。c++

直到前不久看到一個說法,好像知道了一丟丟:es6

構造函數執行的時候會像普通函數同樣,造成一個私有做用域,執行前會建立一個實例對象,讓this指向這個對象,讓實例對象的__proto__屬性指向構造函數的原型即構造函數的prototype屬性,執行完成後將這個對象返回。閉包

舉個例子:函數

function Fn(x, y) {
    //咱們假設到了new Fn執行階段,建立實例對象{__proto__:Object},將this指向實例對象,
    // 將實例的__proto__屬性指向Fn.prototype獲得{__proto__:Object}
    this.a = x  //將x賦值賦值給實例對象中的a,獲得 {a:x, __proto__:Object}
    this.b = y  //將y給實例中的b {a:x, b: y, __proto__:Object}
    var c = x   //Fn中保存的x
    this.getNum = function () {  //將函數給實例中的getNum屬性,
        // 獲得{a:x, b: y, getNum: f..., __proto__:Object}
        console.log(this.a)
        console.log(c++)
    }
    //將獲得的實例做爲返回值返回
}
var f = new Fn(1, 1)
console.log(f) // =》{a: 1,b: 1,getNum: ƒ (),__proto__: Object}
f.getNum() // =》1,1
f.getNum() // =》1,2 c做爲Fn執行時保存在做用域內的私有變量,
// getNum在這個做用域中建立,因此Fn此次執行的做用域是getNum的上級做用域,訪問c時會像上級做用域查找
console.log(f.a) // =>1 f中有a屬性
console.log(f.c) // =》undefined f中沒有c屬性
Fn.setStatic = function () {   //給Fn定義個靜態方法
    console.log('我是靜態方法')
}
Fn.setStatic() //調用靜態方法
複製代碼

關於Fn執行內存不釋放的閉包機制,能夠看前兩天寫的我瞎說的閉包post

以上都是在es5中,在es6中咱們有了class語法糖:ui

class Fn {
    constructor(x,y){
        this.a = x
        this.b = y
        let c = x //設置私有變量
        this.getNum = function () {
            console.log(c++)
            console.log(this.a)
        }
    }
    say(){  //沒有this的時候,函數定義在Fn的原型鏈上
        console.log(this.a)
    }
    static setStatic() {  //設置靜態函數
        console.log('我是靜態方法')
    }
}

let f = new Fn(1, 1)
console.log(f)  // {a: 1, b: 1, getNum: ƒ ()}
console.log(f.__proto__.say) // => say(){console.log(this.a)} 是函數say
f.say() //1
f.getNum() //1, 1
f.getNum() //1,2
Fn.setStatic()  // 調用靜態方法
複製代碼
相關文章
相關標籤/搜索