摘要:作者陳大魚頭鏈接背景最近高級前端工程師劉小夕在上開了個每個工作日布一個前端相關題的,懷著學習的心態(tài)我也參與其中,以下為我的回答,如果有不對的地方,非常歡迎各位指出。當一個函數(shù)用作構造函數(shù)時使用關鍵字,它的被綁定到正在構造的新對象。
作者:陳大魚頭
github: KRISACHAN
鏈接:github.com/YvetteLau/S…
背景:最近高級前端工程師 劉小夕 在 github 上開了個每個工作日布一個前端相關題的 repo,懷著學習的心態(tài)我也參與其中,以下為我的回答,如果有不對的地方,非常歡迎各位指出。
今天我們分享的是第一題:如何正確判斷this的指向?
例子<script>
// 瀏覽器正常情況下
console.log(this === window) // true
script>
<script>
// 函數(shù)調用
a = 10;
function fn1 () {
console.log(this.a)
}
fn1() // 10
b = 2
console.log(this.b) //2
function fn2 () {
this.b = 3
}
fn2()
console.log(this.b) // 3
script>
<script>
// 方法調用
function test () {
console.log(this.x)
}
x = 2
var o = {}
o.x = 1
o.m = test
o.m() // 1
script>
<script>
// 構造函數(shù)調用
x = 2
function test () {
this.x = 1
}
var o = new test()
console.log(x) // 2
script>
<script>
// apply調用
x = 0
function test () {
console.log(this.x)
}
var o = {}
o.x = 1
o.m = test
o.m.apply(o) // 1
script>
<script>
// 函數(shù) apply調用
var zz = {};
zz.a = 1000;
a = 10;
function fn1 () {
console.log(this.a)
}
fn1.apply(zz) // 1000
b = 2
console.log(this.b) //2
function fn2 () {
this.b = 3
}
fn2.apply(zz)
console.log(this.b) // 2
script>
<script>
// 函數(shù) apply調用
var qqq = {
a: 1
}
var ttt = {
a: 2
}
var mmm = {
a: 3
}
function fq () {
console.log(this)
}
fq.bind(qqq).bind(ttt).bind(mmm)() // {a: 1}
script>
<script>
// forEach
var arr = [1, 2, 3, 4]
var newarr = [5, 6, 7, 8]
var newnewarr = [9, 10, 11, 12]
arr.forEach(function (e, i, a) {
console.log(this) // newarr
}, newarr)
arr.forEach((e, i, a) => {
console.log(this) // window
}, newarr)
script>
<script>
// 立即執(zhí)行函數(shù)
(function () {
console.log(this) // window
})()
var o = {};
o.x = 999;
(function () {
console.log(this) // {x:999}
}).apply(o)
;(() => {
console.log(this) // window
})()
;(() => {
console.log(this) // window
}).apply(o)
script>
<script>
"use strict"
console.log(this === window) // true
script>
<script>
"use strict"
var k = {
a: 1,
b: 2,
c: 3
}
const fn1 = function () {
console.log(this)
}
fn1() // undefined
fn1.apply(k) // {a: 1, b: 2, c: 3}
k.m = fn1
k.m() // {a: 1, b: 2, c: 3, m: ?}
script>
<script>
"use strict"
const o = {
a: 1,
b: 2,
c: 3
}
const fn2 = () => {
console.log(this)
}
fn2() // window
fn2.apply(o) // window
o.m = fn2
o.m() // window
script>
<script>
"use strict"
const oo = {
d: function () {
console.log(this)
},
e: () => {
console.log(this)
}
}
const ooo = {
a: 1,
b: 2,
c: 3
}
oo.d() // {d: ?, e: ?}
oo.e() // window
oo.d.apply(ooo) // {a: 1, b: 2, c: 3}
oo.e.apply(ooo) // window
var xxx = oo.d
var yyy = oo.e
xxx() // undefined
yyy() // window
script>
<script>
"use strict"
// forEach
var arr = [1, 2, 3, 4]
var newarr = [5, 6, 7, 8]
var newnewarr = [9, 10, 11, 12]
arr.forEach(function (e, i, a) {
console.log(this) // newarr
}, newarr)
arr.forEach((e, i, a) => {
console.log(this) // window
}, newarr)
script>
總結
上面簡單列了 window 下的幾種情況,但其實在node下的情況也類似。 其實法則總結起來就是下面幾點:
無論是否在嚴格模式下,在全局執(zhí)行環(huán)境中(在任何函數(shù)體外部) this 都指向全局對象。
簡單函數(shù)調用, this 在一般模式下指向全局對象;嚴格模式下 this 默認為 ndefined 。
call , bind, apply在非箭頭函數(shù)下修改 this 值;箭頭函數(shù)下無法修改(由于 箭頭函數(shù)沒有自己的this指針,通過 call() 或 apply() 方法調用一個函數(shù)時,只能傳遞參數(shù)),不管call , bind, apply多少次,函數(shù)的 this 永遠由第一次的決定。
當函數(shù)作為對象里的方法被調用時,它們的 this 是調用該函數(shù)的對象。
如果該方法存在于一個對象的原型鏈上,那么this指向的是調用這個方法的對象,就像該方法在對象上一樣。
當一個函數(shù)用作構造函數(shù)時(使用new關鍵字),它的this被綁定到正在構造的新對象。
在ECMA內, this 會調用 原生方法 ResolveThisBinding() 原生方法ResolveThisBinding使用正在運行的執(zhí)行上下文的LexicalEnvironment確定關鍵字this的綁定。 ResolveThisBinding執(zhí)行以下步驟:
設置 envRec 為 GetThisEnvironment();
返回 envRec.GetThisBinding() 。
原生方法GetThisEnvironment找到當前提供關鍵字 this 綁定的環(huán)境記錄。 GetThisEnvironment 執(zhí)行以下步驟:
設置 lex 為??正在運行的執(zhí)行上下文的 LexicalEnvironment 。
重復以下行為: a. 設置 envRec 為 lex 的 環(huán)境記錄; b. 設置 exists 為 envRec.HasThisBinding() c. 如果 exists 為真,返回出 envRec d.設置 outer 為 lex 的外部環(huán)境參考值。 e. 斷言: outer 不是 null f. 設置 lex 為 outer
注意:步驟2中的循環(huán)必須終止,因為列表的環(huán)境總是以全局環(huán)境這個綁定。
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://www.ezyhdfw.cn/yun/6906.html
摘要:期深拷貝與淺拷貝的區(qū)別如何實現(xiàn)一個深拷貝在回答這個問題前,我們先來回顧一下中兩大數(shù)據(jù)類型基本類型引用類型基本類型基本類型就是值類型存放在棧內存中的簡單數(shù)據(jù)段,數(shù)據(jù)大小確定,內存空間大小可以分配引用類型引用類型存放在堆內存中的對象,變量實際保 20190311期 深拷貝與淺拷貝的區(qū)別?如何實現(xiàn)一個深拷貝 在回答這個問題前,我們先來回顧一下JS中兩大數(shù)據(jù)類型 基本類型 Undefined...
摘要:靜態(tài)作用域與動態(tài)作用域靜態(tài)作用域函數(shù)的作用域基于函數(shù)創(chuàng)建的位置。采用的是詞法作用域,也稱為靜態(tài)作用域??梢越俪终麄€對象,并返回一個新的對象。防誤觸延緩執(zhí)行立即執(zhí)行節(jié)流所謂節(jié)流,就是指連續(xù)觸發(fā)事件但是在秒中只執(zhí)行一次函數(shù)。 在這里記錄著每天自己遇到的一道印象深刻的前端問題,以及一道生活中隨處可見的小問題。 強迫自己形成積累的習慣,鞭撻自己不斷前行,共同學習。 Github 地址 2019...
閱讀 1410·2021-09-22 15:09
閱讀 2848·2021-08-20 09:38
閱讀 2504·2021-08-03 14:03
閱讀 981·2019-08-30 15:55
閱讀 3438·2019-08-30 12:59
閱讀 3615·2019-08-26 13:48
閱讀 1951·2019-08-26 11:40
閱讀 746·2019-08-26 10:30