你不知道的js中關于this綁定機制的解析[看完還不懂算我輸]

前言

最近正在看《你不知道的JavaScript》,里面關于this綁定機制的部分講的特別好,很清晰,這部分對我們js的使用也是相當關鍵的,并且這也是一個面試的高頻考點,所以整理一篇文章分享一下這部分的內容,相信看本文的解析,你一定會有所收獲的,如果喜歡的話可以點波贊/關注,支持一下。

個人博客了解一下:obkoro1.com


為什么要用this:

function identify() {console.log("Hello,I'm " + this.name);
}
let me = {name: "Kyle"
};
let you = {name: "Reader"
};
identify.call(me); // Hello,I'm Kyle
identify.call(you); // Hello,I'm Reader
復制代碼

這個簡單的栗子,可以在不同的對象中復用函數identify,不用針對每個對象編寫一個新函數。

this解決的問題:

this提供了一種更優雅的方法來隱式'傳遞'一個對象的引用,因此可以將API設計得更加簡潔并且易于復用

this的四種綁定規則:

默認綁定:

規則:在非嚴格模式下,默認綁定的this指向全局對象,嚴格模式下this指向undefined

function foo() {console.log(this.a); // this指向全局對象
}
var a = 2;
foo(); // 2
function foo2() {"use strict"; // 嚴格模式this綁定到undefinedconsole.log(this.a); 
}
foo2(); // TypeError:a undefined
復制代碼

默認綁定規則如上述栗子,書中還提到了一個微妙的細節:

function foo() {console.log(this.a); // foo函數不是嚴格模式 默認綁定全局對象
}
var a = 2;
function foo2(){"use strict";foo(); // 嚴格模式下調用其他函數,不影響默認綁定
}
foo2(); // 2
復制代碼

所以:對于默認綁定來說,決定this綁定對象的是函數體是否處于嚴格模式,嚴格指向undefined,非嚴格指向全局對象。

通常不會在代碼中混用嚴格模式和非嚴格模式,所以這種情況很罕見,知道一下就可以了,避免某些變態的面試題挖坑。

隱式綁定:

規則:函數在調用位置,是否有上下文對象,如果有,那么this就會隱式綁定到這個對象上。

    function foo() {console.log(this.a);}var a = "Oops, global";let obj2 = {a: 2,foo: foo};let obj1 = {a: 22,obj2: obj2};obj2.foo(); // 2 this指向調用函數的對象obj1.obj2.foo(); // 2 this指向最后一層調用函數的對象// 隱式綁定丟失let bar = obj2.foo; // bar只是一個函數別名 是obj2.foo的一個引用bar(); // "Oops, global" - 指向全局
復制代碼

隱式綁定丟失:

隱式綁定丟失的問題:實際上就是函數調用時,并沒有上下文對象,只是對函數的引用,所以會導致隱式綁定丟失。

同樣的問題,還發生在傳入回調函數中,這種情況更加常見,并且隱蔽,類似:

    test(obj2.foo); // 傳入函數的引用,調用時也是沒有上下文對象。
復制代碼

顯式綁定:

就像我們上面看到的,如果單純使用隱式綁定肯定沒有辦法得到期望的綁定,幸好我們還可以在某個對象上強制調用函數,從而將this綁定在這個對象上

規則:我們可以通過applycallbind將函數中的this綁定到指定對象上。

function foo() {console.log(this.a);
}
let obj = {a: 2
};
foo.call(obj); // 2
復制代碼

傳入的不是對象:

如果你傳入了一個原始值(字符串,布爾類型,數字類型),來當做this的綁定對象,這個原始值轉換成它的對象形式。

如果你把null或者undefined作為this的綁定對象傳入call/apply/bind,這些值會在調用時被忽略,實際應用的是默認綁定規則。

new綁定:

書中提到:在js中,實際上并不存在所謂的'構造函數',只有對于函數的'構造調用'。

new的時候會做哪些事情:

  1. 創建一個全新的對象
  2. 這個新對象會被執行 [[Prototype]] 連接。
  3. 這個新對象會綁定到函數調用的this
  4. 如果函數沒有返回其他對象,那么new表達式中的函數調用會自動返回這個新對象。

規則:使用構造調用的時候,this會自動綁定在new期間創建的對象上。

function foo(a) {this.a = a; // this綁定到bar上
}
let bar = new foo(2);
console.log(bar.a); // 2
復制代碼

this四種綁定規則的優先級

如果在某個調用位置應用了多條規則,如何確定哪條規則生效?

    obj.foo.call(obj2); // this指向obj2 顯式綁定比隱式綁定優先級高。new obj.foo(); // thsi指向new新創建的對象 new綁定比隱式綁定優先級高。
復制代碼

顯式綁定和new綁定無法直接比較(會報錯),默認綁定是不應用其他規則之后的兜底綁定所以優先級最低,最后的結果是:

顯式綁定 > 隱式綁定 > 默認綁定

new綁定 > 隱式綁定 > 默認綁定

箭頭函數的this指向不會使用上述的四條規則:

function foo() {return () => {console.log(this.a);};
}
let obj1 = {a: 2
};
let obj2 = {a: 22
};
let bar = foo.call(obj1); // foo this指向obj1
bar.call(obj2); // 輸出2 這里執行箭頭函數 并試圖綁定this指向到obj2
復制代碼

從上述栗子可以得出,箭頭函數的this規則:

  1. 箭頭函數中的this繼承于它外面第一個不是箭頭函數的函數的this指向
  2. 箭頭函數的 this 一旦綁定了上下文,就不會被任何代碼改變

結語

認真看完的話,相信你已經get到this的用法了,最后推薦一下《你不知道的JavaScript》,這本書真的很好,寫的也很有趣,沒看過的小伙伴抓緊入手了。

PS:目前離職中,大佬們有坑位可以介紹一下呀,base:上海長寧。


原文發布時間:2018-6-20
原文作者: OBKoro1
本文來源掘金如需轉載請緊急聯系作者

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/538445.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/538445.shtml
英文地址,請注明出處:http://en.pswp.cn/news/538445.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

visual studio過期登錄不了賬戶_具有最高管理權限賬戶,Windows 7設置Administrator密碼永不過期...

今天介紹操作系統具有最高管理權限的賬戶,Windows 7如何設置Administrator賬戶密碼永不過期。小伙伴們可能不知道,和Windows Vista操作系統一樣,在Windows 7操作系統中是不能預先使用Administrator這個具有最高管理權限的賬戶的。同時也可能不…

Tomcat安裝與環境變量的配置-Linux+windows

原文鏈接:http://jingyan.baidu.com/article/8065f87fcc0f182330249841.html ------------------------------------------------------------ 1,新建變量名:JAVA_HOME,變量值:C:\Program Files\Java\jdk1.7.0 2&…

python如何讀取配置文件獲取url以及hhead_讀取INI配置文件內容(頭文件head)

/************************************************************FileName: getini.h // 文件名稱Author: yuanfen127 // 作者Date: 2005-03-31 // 日期Description: // 描述本文件的內容,功能,內部各部分之間的關系// 以及文本文件與…

cad隱藏圖層命令快捷鍵_cad快捷鍵f是什么命令?cad中f快捷鍵都有哪些?

1. F1 該功能鍵打開AutoCAD幫助窗口。如果用戶遇到此軟件中的任何功能問題,它可以使用戶在線獲得幫助。如果用戶離線工作,而不是按此鍵,則該軟件的所有功能都將以PDF格式打開。 2. F2 該鍵將打開一個彈出屏幕,在底部顯示命令行。該命令對于在屏幕底部看不到命令窗口的用戶很…

angular2或4部署到tomcat中,讓他跑起來

原文地址:http://blog.csdn.net/rotating_windmill/article/details/76768793 ------------------------------------------------------------------------- 首先使用構建命令(npm run build或ng build)打包,打包完成后項目中會出現一個dist的目錄&…

java 高級編程進階_JAVA高級編程之hibernate進階學習

二級緩存hibernate的session緩存在事務級別進行持久化數據的緩存操作。 當然,也有可能分別為每個類(或集合),配置集群、或 JVM 級別(SessionFactory 級別)的緩存。你甚至可以為之插入一個集群的緩存。注意,緩存永遠不知道其他應用程序對持久化…

SpringMvc+Tomcat+Angular4 部署運行

這次的團隊開發是,前端開發人員和后臺開發人員完全分開開發的。 前端開發采用了Angular4,webstorm 后端開發采用了:springspringmvcmybatis,eclipse --------------------------------------- 最后要整合了。 1、angular項目編…

python爬蟲本科容易找工作嗎_python爬蟲基礎學完了,我真的能找到一份工作嗎?...

1.能不能找到工作我覺得取決于你技術掌握的程度。2.無論在什么領域,只要你技術到家,都不用愁找不到工作。3.多數人問他們轉行能不能找到工作,是想知道這個崗位需要的人多不多,在爬蟲這個領域,從事這方面的人應該也不少…

jqgrid demo java_java – jqgrid如何顯示服務器端消息

我使用jqGrid以表格格式顯示數據,使用JSP和servlet.編輯我想在執行插入,更新,刪除等操作時顯示來自服務器的錯誤. (數據類型:“xml”)jqGrid的jQuery("#list10_d").jqGrid({height:250,width:600,url:Assignment?actionAssign,datatype: "xml"…

IPv4地址分類及特征

IPv4地址分類及特征 IP地址后斜杠和數字代表的意思 其中有這樣一個IP地址的格式:IP/數字,例如:111.222.111.222/24這種格式平時在內網中用的不多,所以一下子看不懂,最后查了資料才知斜杠后的數字代表的是掩碼的位數 “…

查看Scala編譯的.class文件

Scala是基于JDK運行的,必然會生成Java的字節碼文件.class文件。 如何查看? 編碼IDE:IntelliJ IDEA 2017.2 x64 查看class文件工具:jd-gui scala代碼如下: person.scala package cn.zengmg.day26class Person {val …

python傳文件給堡壘機上遠程的另一個機器_如何用hive調度堡壘機上的python腳本...

工作中,如果我們本地要操作的數據量大,那么主機是跑不起來python腳本的,這個時候,就要用到服務器(也叫堡壘機)了。那么如何用HIVE調用堡壘機上的python腳本呢?今天小白就總結一下步驟和一些注意事項~1.首先將Python腳本…

SecureCRT如何導出導入配置文件

以SecureCRT7.2.5為例 Options-----Global Options -----General -----Configuration Paths 備份: 進入該文件夾,復制里面的內容到要備份的地方 還原: 將上面的復制的文件,拷貝到 Configuration Paths 下

【原創】利用騰訊和百度的AI接口識別驗證碼

眾所周知,驗證碼在大部分的實際運用中是繞不開的問題,包括驗證,爬蟲,測試等等,然后解決驗證碼的方法也有不少,但大多數都會運用OCR。(這里說的驗證碼,是字符類型的驗證碼&#xff09…

在java中5 % 3_Java基礎5

Java多線程:進程:進行中的程序線程:就是進程中一個負責程序執行的控制單元(執行單元)一個進程中可以多執行路徑,稱之為多線程一個進程至少一個線程開啟多個線程是為了同時運行多部分代碼每個線程都有自己運行的內容,這個內容成為線程要執行的任務多線程的…

scala中:: , +:, :+, :::, +++的區別

原文鏈接:https://segmentfault.com/a/1190000005083578 ------------------------------------------------------------- 4種操作符的區別和聯系 :: 該方法被稱為cons,意為構造,向隊列的頭部追加數據,創造新的列表。用法為 x::…

python包管理機制_Go 1.5之前的多種包管理機制簡介(

在 Go 語言中,我們可以使用go get命令安裝遠程倉庫中托管的代碼,不同于 Ruby Gem、pypi 等集中式的包管理機制, Go 語言的包管理系統是去中心化的。簡單來講,go get命令支持任何一個位置托管的 Git 或 Mercurial 的倉庫&#xff0…

nc命令簡介

nc介紹 ncat/nc 既是一個端口掃描工具,也是一款安全工具,還能是一款監測工具,甚至可以做為一個簡單的 TCP 代理。 在大多數 Debian 發行版中,nc 是默認可用的,它會在安裝系統的過程中自動被安裝。 但是在 CentOS 7 / R…

java時間日期工具類_java工具類--日期相關;

日期相關Date類1.通常使用的是java.util包2.導包 拿來使用 構建對象3.通常使用無參數的構造方法 或者帶long構造方法4.Date類中常用的方法before(); after();setTime() getTime()compareTo(); -1 1 0;5.可以處理一個Date類型的格式DateFormat類1.包java.text 需要導包使用2.此類…

/* compiled code */ ?

原因:這是所用的ide自帶了反編譯工具,反編譯的。不是具體的源碼 具體的源碼需要手動關聯源碼包