摘要:的指向只和函數(shù)的調(diào)用位置方式有關(guān),和函數(shù)聲明的位置無關(guān)。全局瀏覽器全局這是中的默認(rèn)綁定,在全局上下文中,會默認(rèn)綁定到全局對象。同時上面四條綁定規(guī)則在箭頭函數(shù)中不適用,使得的查找更可控。
本文共 1065 字,讀完只需 4 分鐘概述
在 JAVA 中,this 的概念很透徹,就是指向當(dāng)前對象(方法和屬性的持有者),在編譯的時候就能確定 this 指代,而由于 JavaScript 中 this 是動態(tài)綁定,或稱為運行期綁定的,在絕大多數(shù)情況下,函數(shù)的調(diào)用方式?jīng)Q定了 this 的值,所以在 JS 中不能在定義時決定地定義 this 是哪個上下文對象。
this 的指向只和函數(shù)的調(diào)用位置(方式)有關(guān),和函數(shù)聲明的位置無關(guān)。
本文就從 this 應(yīng)用場景調(diào)用方式的角度,解析 this 的用法。
首先,要知道,this 的作用是什么?
函數(shù)體內(nèi)部,指代函數(shù)當(dāng)前的運行上下文。一、全局上下文
在全局上下文中,this 指向全局對象,在瀏覽器中指向 window,在 NodeJs 中指向 global。
var a = "全局"; console.log(this) // 瀏覽器:window console.log(this) // nodejs:global console.log(this.a) // "全局"
這是 JS 中的默認(rèn)綁定,在全局上下文中,this 會默認(rèn)綁定到 全局對象。
二、函數(shù)聲明在非嚴(yán)格模式下,未加關(guān)鍵字 var 聲明的變量,會成為全局對象下的屬性,所以,此時
在嚴(yán)格模式下,this 將保持他進(jìn)入執(zhí)行上下文時的值,所以下面的 this 將會默認(rèn)為 undefined。
function foo() { "use strict"; console.log(this); } foo(); // undefined 嚴(yán)格模式
上述也是 JS 中 this 的默認(rèn)綁定,在函數(shù)定義中,函數(shù)中的 this 會默認(rèn)綁定到全局對象或者 undefined。
當(dāng)函數(shù)作為對象里的方法被調(diào)用時,函數(shù)中 this 是調(diào)用該函數(shù)的對象。
function foo() { console.log("foo"); } var obj = { this.bar = "bar"; this.foo = foo; } obj.foo(); // "foo"
在調(diào)用位置,是 obj 對象調(diào)用了 foo 函數(shù),此時 this 就指向了 obj 對象。
function foo() { console.log(this.bar); } var obj2 = { bar: "2", foo: foo } var obj1 = { bar: "1", obj2: obj2 } obj1.obj2.foo() // "2";
這是 JS 中 this 的隱式綁定,this 會隱式綁定到調(diào)用的最近一層上下文對象。
三、call & apply其實在函數(shù)中,函數(shù)正確的調(diào)用應(yīng)該是用 call, apply 函數(shù)的形式。
function foo() { console.log(this.bar); } let obj = { bar: "1", foo: foo } obj.foo(); // `.` 點調(diào)用其實是語法糖 foo.call(obj) // 1 正確的姿勢 foo.apply(obj) // 1
這是 JS 中 this 的顯式綁定,函數(shù)通過從 call 和 apply 函數(shù)可以顯式指定函數(shù)的調(diào)用對象。
ES5 提供了一個 bind()方法:
let obj2 = { a: 2 } let foo = function () { console.log(this.a); } let bar = foo.bind(obj2); bar() // 2;
就是 JS 中 this 的硬綁定,bind() 函數(shù)會返回一個指定了調(diào)用對象的函數(shù),返回的函數(shù)的被指定了 this 且 this 無法改變。
四、構(gòu)造函數(shù)當(dāng)函數(shù)加上關(guān)鍵字 new 后,函數(shù)會變成一個構(gòu)造函數(shù),此時構(gòu)造函數(shù)中的 this 指向即將創(chuàng)建的對象實例,同時對象實例會關(guān)聯(lián)到構(gòu)造函數(shù)的原型對象 prototype 上。
function Foo() { this.a = 3; } var obj = new Foo(); obj.a // 3五、箭頭函數(shù)
ES6 中,提供了函數(shù)定義的語法糖,讓定義函數(shù)變得更簡潔(沒有 arguments, 沒有原型)。同時上面四條綁定規(guī)則在箭頭函數(shù)中不適用,使得 this 的查找更可控。
// 一般函數(shù): var a = 1; var obj = { a: 2, say: function() { console.log(this.a) } } obj.say(); // console.log 打印值為 2 // 箭頭函數(shù) var a = 1; var obj = { a: 2, say: () => { console.log(this.a) } } obj.say(); // 1 !!!
由于箭頭函數(shù)定義時, obj {} 不是執(zhí)行上下文,say 變量引用的箭頭函數(shù),其 this 是父級執(zhí)行上下文,也就是全局上下文,所以 this.a 就是 全局變量 a: 1;
在箭頭函數(shù)中,this 與封閉詞法上下文的 this 保持一致,this 被永久綁定到了它最近一層非箭頭函數(shù)的 this,而與函數(shù)的調(diào)用位置無關(guān)。
總結(jié)在絕大多數(shù)情況下,函數(shù)的調(diào)用方式?jīng)Q定了 this 的值,但最終都指向了調(diào)用了它的那個上下文對象。
歡迎關(guān)注我的個人公眾號“謝南波”,專注分享原創(chuàng)文章。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/98533.html
摘要:深入系列第七篇,結(jié)合之前所講的四篇文章,以權(quán)威指南的為例,具體講解當(dāng)函數(shù)執(zhí)行的時候,執(zhí)行上下文棧變量對象作用域鏈?zhǔn)侨绾巫兓?。前言在深入之?zhí)行上下文棧中講到,當(dāng)代碼執(zhí)行一段可執(zhí)行代碼時,會創(chuàng)建對應(yīng)的執(zhí)行上下文。 JavaScript深入系列第七篇,結(jié)合之前所講的四篇文章,以權(quán)威指南的demo為例,具體講解當(dāng)函數(shù)執(zhí)行的時候,執(zhí)行上下文棧、變量對象、作用域鏈?zhǔn)侨绾巫兓摹?前言 在《Jav...
摘要:也就是說當(dāng)返回的函數(shù)作為構(gòu)造函數(shù)的時候,時指定的值會失效,但傳入的參數(shù)依然生效。構(gòu)造函數(shù)效果的優(yōu)化實現(xiàn)但是在這個寫法中,我們直接將,我們直接修改的時候,也會直接修改函數(shù)的。 JavaScript深入系列第十一篇,通過bind函數(shù)的模擬實現(xiàn),帶大家真正了解bind的特性 bind 一句話介紹 bind: bind() 方法會創(chuàng)建一個新函數(shù)。當(dāng)這個新函數(shù)被調(diào)用時,bind() 的第一個參數(shù)...
摘要:深入系列第十二篇,通過的模擬實現(xiàn),帶大家揭開使用獲得構(gòu)造函數(shù)實例的真相一句話介紹運算符創(chuàng)建一個用戶定義的對象類型的實例或具有構(gòu)造函數(shù)的內(nèi)置對象類型之一也許有點難懂,我們在模擬之前,先看看實現(xiàn)了哪些功能。 JavaScript深入系列第十二篇,通過new的模擬實現(xiàn),帶大家揭開使用new獲得構(gòu)造函數(shù)實例的真相 new 一句話介紹 new: new 運算符創(chuàng)建一個用戶定義的對象類型的實例或具...
摘要:深入系列第十五篇,講解各種繼承方式和優(yōu)缺點。優(yōu)點融合原型鏈繼承和構(gòu)造函數(shù)的優(yōu)點,是中最常用的繼承模式。寄生組合式繼承為了方便大家閱讀,在這里重復(fù)一下組合繼承的代碼組合繼承最大的缺點是會調(diào)用兩次父構(gòu)造函數(shù)。 JavaScript深入系列第十五篇,講解JavaScript各種繼承方式和優(yōu)缺點。 寫在前面 本文講解JavaScript各種繼承方式和優(yōu)缺點。 但是注意: 這篇文章更像是筆記,哎...
摘要:在全局對象中調(diào)用,自然讀取的是全局對象的值構(gòu)造器調(diào)用說明作為構(gòu)造器調(diào)用時,指向返回的這個對象。最直觀的表現(xiàn)就是,去看一些優(yōu)秀框架的源代碼時,不再是被繞的暈乎乎的。 學(xué)習(xí)起因: 在之前的JavaScript學(xué)習(xí)中,this,call,apply總是讓我感到迷惑,但是他們的運用又非常的廣泛。遂專門花了一天,來弄懂JavaScript的this,call,apply。中途參考的書籍也很多,以...
摘要:深入系列第十四篇,講解創(chuàng)建對象的各種方式,以及優(yōu)缺點。也就是說打著構(gòu)造函數(shù)的幌子掛羊頭賣狗肉,你看創(chuàng)建的實例使用都無法指向構(gòu)造函數(shù)這樣方法可以在特殊情況下使用。 JavaScript深入系列第十四篇,講解創(chuàng)建對象的各種方式,以及優(yōu)缺點。 寫在前面 這篇文章講解創(chuàng)建對象的各種方式,以及優(yōu)缺點。 但是注意: 這篇文章更像是筆記,因為《JavaScript高級程序設(shè)計》寫得真是太好了! 1....
閱讀 3994·2021-09-22 16:03
閱讀 5344·2021-09-22 15:40
閱讀 1197·2021-09-06 15:02
閱讀 878·2019-08-30 15:53
閱讀 2231·2019-08-29 15:35
閱讀 1116·2019-08-23 18:22
閱讀 3345·2019-08-23 16:06
閱讀 652·2019-08-23 12:27