之前一直很迷惑new一個函式到底是個啥,筆記本上到處戳戳,還有不同時期的不同理解。理解A:new X 是建立一個繼承X.prototype的物件。理解B:使用new呼叫一個函式,將會建構函式的作用域付給新物件:a = new B()把B的this給a。????????????我記的啥,怎麼看起來那麼迷惑。
直到前不久看到一個說法,好像知道了一丟丟:
建構函式執行的時候會像普通函式一樣,形成一個私有作用域,執行前會建立一個例項物件,讓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執行記憶體不釋放的閉包機制,可以看前兩天寫的我瞎說的閉包。
以上都是在es5中,在es6中我們有了class語法糖:
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() // 呼叫靜態方法
複製程式碼