js的做用域鏈,原型鏈,以及閉包函數理解

代碼一:數組

this.number = 10
function a() {
  this.number = 20
}
a.prototype.init = () => console.log(this.number)

const test = new a() // 構造函數生成一個獨立新對象
test.init() // 10

解析:之因此輸出10,能夠把 arrow function(箭頭函數) 裏的 this 和 arguments 關鍵字理解爲函數做用域裏的變量(由於自身沒有),他訪問變量沿着做用域鏈向上找而不是直接訪問對象屬性走原型鏈,代碼中的init上頭的做用域就是window,因此他的this指向window.閉包

注:能夠試試把上例代碼中的箭頭函數換成普通匿名函數(輸出就是直接走原型鏈訪問對象屬性,number = 20)app

代碼二:函數

this.number = 10
function a(){ //閉包函數 return {
     show: () => console.log(this.number)  } } a().show() // 10 函數a的this的指向window
a.call({number: 20}).show() // 20 call改變了函數a的this指向,箭頭函數的做用域指向改變後的函數做用域
a.call({number: 30}).show() // 30

解析:閉包函數裏return出的箭頭函數被調用的時候會一直引用外層函數的變量this或者arguments,因此外層函數this指向被改變,return出的箭頭函數裏的this也改變了.this

this的指向可理解爲兩大類:spa

1:test();==test.call(window,參數);//直接調用函數,this指向windowprototype

2:obj.test(); == obj.test.call(obj,參數);//函數做爲對象的方法被調用,this指向該對象code

注:this指向是在被調用時分配的對象

代碼三:blog

function a() {
 this.say = function() {
 console.log(1)
}
}
a.prototype.say = function() {
console.log(2)
}
var test = new a()
test.say() // 1

只有函數有prototype,對象對應_proto_,prototype能夠對主函數進行擴充,但不會覆蓋主函數內的方法(若是主函數裏沒有此對象屬性就在原型鏈裏查找)。

簡單一句話~js中訪問變量沿着做用域鏈向上走(this),直接訪問對象上的屬性沿着原型鏈往下走~(都是就近查找哦)

對call和apply作補充:

相同點:都是爲了改變對象this指向,參數二不一樣:call是傳進單個參數,apply是數組形式

apply能夠接受一個數組或者類數組對象,console.log(...arguments) === console.log.apply(this,arguments)

相關文章
相關標籤/搜索