摘要:在用創(chuàng)建對象時,指向發(fā)生改變是在第二步創(chuàng)建一個對象實例將構造函數中的指向這個對象執(zhí)行構造函數中的代碼返回這個新創(chuàng)建的對象箭頭函數中的箭頭函數內部是不會綁定的,它會捕獲外層作用域中的,作為自己的值。參考你不知道的上卷
前言
this 是 JavaScript 中不可不談的一個知識點,它非常重要但又不容易理解。因為 JavaScript 中的 this 不同于其他語言。不同場景下的 this 指向不同(當函數被調用執(zhí)行時會生成變量對象,確定 this 的指向,因此當前函數的 this 是在函數被調用執(zhí)行的時候才確定的,所以導致 this 的指向靈活不確定),而且,在嚴格模式和非嚴格模式下,this 也會有不同的解讀。
為什么要有 this先想想如果 JavaScript 中沒有 this 會怎么樣?比如下面這段代碼:
function identity(context) { return context.name.toUpperCase(); } function speak(context) { var greeting = "Hello, I am " + identity(context) console.log(greeting) } var you = { name: "Reader" } var me = { name: "Stone" } identity(you); // READER speak(me); // Hello, I am Stone
我們給這 identity 和 speak 兩個函數顯示的傳入了一個上下文對象,這似乎看不出什么,但是一旦你的應用變得越來越復雜,這種顯示傳遞上下文就會讓代碼越來越混亂,代碼結構越來越模糊。而使用 this 就可以避免這樣,因為 this 提供了一種更優(yōu)雅的方式來隱式傳遞對象引用,可以把 API 設計得更加簡潔易用。
this 的綁定規(guī)則 全局對象中的 this全局對象的變量對象是一個比較特殊的存在,在全局對象中,this 指向它本身,比如:
// this 綁定到全局對象 this.a1 = 10; // 通過聲明綁定到變量對象,全局環(huán)境中,變量對象就是它本身 var a2 = 20; // 會隱式綁定到全局對象 a3 = 30; console.log(a1); // 10 console.log(a2); // 20 console.log(a3); // 30函數中的 this
在一個函數的執(zhí)行上下文中,this 由該函數的調用者提供,由函數的調用方式來決定 this 的指向。下面這個例子:
function fn() { console.log(this) } fn(); // Window {...}
默認全局對象就是調用者,等價于 window.fn()(只討論瀏覽器中全局對象)。但是在非嚴格模式中,this 是指向 undefined 的,比如:
"use strict"; function fn() { console.log(this); } fn(); // undefined window.fn(); // Window {...}
這就說明了,如果不指定函數調用者,在嚴格模式下回默認綁定到全局對象,在非嚴格模式下默認指向 undefined 。
函數是獨立調用,還是被某個對象所調用,是很容易分辨的,比如:
"use strict"; var a = 20; function fn() { var a = 1; var obj = { a: 10, c: this.a + 20 } return obj.c } console.log(window.fn()); // 40 console.log(fn()); // TypeError
對象字面量的形式不會產生自己的作用域,所以 obj 中的 this.a 并不是指向 obj ,而是與函數內部的 this 一樣。因此,當 window.fn() 調用時,fn 內部的 this 指向 window 對象,此時 this.a 訪問全局對象中的 a ;由于是在嚴格模式中,在沒有指明調用者的時候,fn 內部默認指向 undefined,所以在多帶帶調用的時候會報錯。
call/apply/bind 顯示綁定 thisJavaScript 中提供了一個方式可以讓我們手動指定函數內部的 this 指向,也就是前面提到的隱式傳遞對象,它們就是call/apply/bind。這三個方法是 Function 的原型方法,所有函數都可以調用這三個方法。看下面這個例子:
var a = 20; var obj = { a: 40 } function fn() { console.log(this.a); } fn(); // 20 fn.call(obj); // 40 fn.apply(obj); // 40
當函數調用 apply/bind 時,表示執(zhí)行該函數,并且這個函數內部的 this 指向 apply/bind 的第一個參數。
二者的區(qū)別:
call 的第一個參數是函數內部 this 的指向,后續(xù)的參數則是函數執(zhí)行時所需要的參數,一個一個傳遞
apply 的第一個參數與 call 相同,而執(zhí)行函數的參數,則以數組的形式傳入
bind 方法也能指定函數的 this ,但是它不同于call/apply。bind 方法會返回一個新函數,這個函數與原函數有相同的函數體,但是函數內部的 this 被綁定成 bind 方法的第一個參數,后續(xù)參數也是一個一個傳入,并且不會自動執(zhí)行新函數。
構造函數中的 this可以把構造函數看成是普通函數,其中的 this 指向是創(chuàng)建的對象實例,之所以稱之為構造函數,是因為我們會借助 new 操作符來調用函數。在用 new 創(chuàng)建對象時,this 指向發(fā)生改變是在第二步:
創(chuàng)建一個對象實例
將構造函數中的 this 指向這個對象
執(zhí)行構造函數中的代碼
返回這個新創(chuàng)建的對象
function Foo() { this.a = 20 } var foo = new Foo() console.log(foo.a) // 20箭頭函數中的 this
箭頭函數內部是不會綁定 this 的,它會捕獲外層作用域中的 this,作為自己的 this 值。比如:
function Person() { this.age = 20; (() => { this.age++ })() } var p = new Person() console.log(p.age)DOM事件中的 this
當函數被當做監(jiān)聽事件處理函數時, 其 this 指向觸發(fā)該事件的元素 (針對于addEventListener事件)。比如:
click
document.querySelector(".box").addEventListener("click", function(e) { console.log(this) // 這個this指向div.box元素 }, false)總結
this 的使用場景豐富多樣,可以用來實現繼承,實現函數柯里化等,作為開發(fā)者應該清楚各種使用方式以及其內部原理。
參考
你不知道的JavaScript(上卷)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101080.html
摘要:從某些方面來講,這章回顧的函數知識并不是針對函數式編程者,非函數式編程者同樣需要了解。什么是函數針對函數式編程,很自然而然的我會想到從函數開始。如果你計劃使用函數式編程,你應該盡可能多地使用函數,而不是程序。指的是一個函數聲明的形參數量。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson - 《You-Dont-Know-JS》作者 關于譯者:...
摘要:是什么這個單詞是一個代詞,所以應該是指代某些東西搞清楚的關鍵之處,就是要搞清楚指代了什么那么到底指代了什么呢就像你平時指著一個蘋果說指著一個香蕉說同樣,也會因為情況的不同而不同在中按照常規(guī)理解,的值是什么取決于函數如何被調用然而,的值是什么 1. this是什么 this這個單詞是一個代詞,所以this應該是 指代某些東西搞清楚this的關鍵之處,就是要搞清楚this指代了什么 那么t...
摘要:理解的函數基礎要搞好深入淺出原型使用原型模型,雖然這經常被當作缺點提及,但是只要善于運用,其實基于原型的繼承模型比傳統(tǒng)的類繼承還要強大。中文指南基本操作指南二繼續(xù)熟悉的幾對方法,包括,,。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。 怎樣使用 this 因為本人屬于偽前端,因此文中只看懂了 8 成左右,希望能夠給大家?guī)韼椭?...(據說是阿里的前端妹子寫的) this 的值到底...
摘要:例如可以用構造函數實現單例模式。例如當這個構造函數被調用,它會檢查是否存在。工廠模式工廠模式使用工廠方法創(chuàng)建對象,而不指定所創(chuàng)建對象的確切類或構造函數。雖然了解審設計模式很重要,但是不要過度使用它們。 By Sukhjinder Arora | Oct 16, 2018 原文 當你開始了一個新項目,你不會馬上開始編寫代碼。第一步,你必須定義這個項目解決什么問題和適用范圍,然后列出這個項...
閱讀 2307·2023-04-25 14:17
閱讀 1515·2021-11-23 10:02
閱讀 2170·2021-11-23 09:51
閱讀 873·2021-10-14 09:49
閱讀 3384·2021-10-11 10:57
閱讀 2921·2021-09-24 09:47
閱讀 3046·2021-08-24 10:00
閱讀 2298·2019-08-29 18:46