摘要:關(guān)于的全面解析下頁(yè)面鏈接的調(diào)用位置調(diào)用位置就是函數(shù)在代碼中被調(diào)用的位置而不是聲明的位置,尋找調(diào)用位置就是尋找函數(shù)被調(diào)用的位置,最重要的是分析調(diào)用棧就是為了到達(dá)當(dāng)前執(zhí)行位置所調(diào)用的所有函數(shù)。因此,調(diào)用函數(shù)時(shí)被綁定到這個(gè)對(duì)象上,所以和是一樣的。
關(guān)于this的全面解析(下)頁(yè)面鏈接
this的調(diào)用位置調(diào)用位置就是函數(shù)在代碼中被調(diào)用的位置(而不是聲明的位置),尋找調(diào)用位置就是尋找“函數(shù)被調(diào)用的位置”,最重要的是分析調(diào)用棧(就是為了到達(dá)當(dāng)前執(zhí)行位置所調(diào)用的所有函數(shù))。
function baz() { //當(dāng)前調(diào)用棧是baz //當(dāng)前調(diào)用位置是全局位置 console.log("baz"); bar(); //<--bar的調(diào)用位置 } function bar() { //當(dāng)前的調(diào)用棧是baz->bar //因此當(dāng)前的調(diào)用位置在baz中 console.log("bar"); foo(); //<--foo的調(diào)用位置 } function foo() { //當(dāng)前的調(diào)用棧是baz->bar->foo //因此當(dāng)前的調(diào)用位置在bar中 console.log("foo"); } baz(); //<-baz的調(diào)用位置
把調(diào)用棧想象成一個(gè)函數(shù)調(diào)用鏈,如上圖代碼中的樣式,但是這種方法非常麻煩并且容易出錯(cuò)。另一個(gè)查看調(diào)用棧的方法是使用瀏覽器的調(diào)試工具。
綁定規(guī)則首先需要找到調(diào)用位置,然后判斷尋求下列四條規(guī)則中的哪一條。
1 默認(rèn)綁定
首先介紹最常用的函數(shù)調(diào)用類型:獨(dú)立函數(shù)調(diào)用。可以把這條規(guī)則看作是無(wú)法應(yīng)用其他規(guī)則時(shí)的默認(rèn)規(guī)則。
function foo() { console.log(this.a); //<-this指向全局作用域 } var a = 2; foo(); //<-foo調(diào)用位置
在代碼中,foo()是直接使用不帶任何修飾的函數(shù)引用進(jìn)行調(diào)用的,因此只能使用默認(rèn)綁定,無(wú)法應(yīng)用其他規(guī)則。
function foz() { "use strict"; console.log(this.a); //<--嚴(yán)格模式下不能將全局對(duì)象用于綁定 } foz(); //TypeError
2 隱藏綁定
另一條需要考慮的規(guī)則是調(diào)用位置是否有上下文對(duì)象,或者說是否被某個(gè)對(duì)象擁有或者包含,這種說法有時(shí)候會(huì)有誤導(dǎo)。
function foa() { console.log(this.a); } var foaObj = { a: "Hello", foa: foa //<--foa函數(shù)調(diào)用位置 } foaObj.foa();
foa函數(shù)在嚴(yán)格意義上來說不屬于foaObj對(duì)象。然而,調(diào)用位置會(huì)使用foaObj上下文來引用函數(shù),因此可以判斷為函數(shù)調(diào)用時(shí),foaObj對(duì)象包含并引用它。
當(dāng)函數(shù)引用有上下文對(duì)象時(shí),隱式綁定規(guī)則會(huì)把函數(shù)調(diào)用中的this綁定到這個(gè)上下文對(duì)象。因此,調(diào)用foa函數(shù)時(shí)this被綁定到foaObj這個(gè)對(duì)象上,所以this.a 和 foaObj.a 是一樣的。
然而,有一個(gè)常見的this綁定問題就是被隱式綁定的函數(shù)會(huì)丟失綁定對(duì)象,也就是說它會(huì)應(yīng)用默認(rèn)綁定,從而把this綁定到全局對(duì)象或undefined上。
function fob() { console.log(this.a); } var fobObj = { a: "Hello", fob: fob } var focObj = fobObj.fob; var a = 1; //a是全局對(duì)象的屬性 focObj();
focObj引用實(shí)際上是fob函數(shù),所以this綁定的是全局對(duì)象中的a。
3 顯式綁定
就像我們剛才看到的那樣,在分析隱式綁定時(shí),我們必須在一個(gè)對(duì)象內(nèi)部包含一個(gè)指向函數(shù)的屬性,并通過這個(gè)屬性間接引用函數(shù),從而把this間接綁定到這個(gè)對(duì)象上。
JavaScript提供的絕大多數(shù)函數(shù)以及你自己創(chuàng)建的所有函數(shù)都可以使用call(…) 和 apply (…) 方法。
這兩個(gè)方法的第一參數(shù)是一個(gè)對(duì)象,是給this準(zhǔn)備的,接著在調(diào)用函數(shù)時(shí)將其綁定到this。因?yàn)槟憧梢灾苯又付╰his的綁定對(duì)象,因此我們稱之為顯式綁定。
function fod() { console.log(this.a); } var fodObj = { a: 2 } fod.call(fodObj); //2
通過fod.call(…)方法,可以強(qiáng)制把this綁定到fodObj這個(gè)對(duì)象上。
然而,顯示綁定仍然無(wú)法解決之前提出的丟失綁定問題。
但是顯示綁定的一個(gè)變種可以解決這個(gè)問題。
function foh() { console.log(this.a); } var fohObj = { a: 2 } var baa = function() { foh.call(fohObj); } baa(); //2 setTimeout(baa, 100); //2 baa.call(window); //2
我們創(chuàng)建了一個(gè)baa函數(shù),并在它的內(nèi)部手動(dòng)調(diào)用了foh.call(fohObj),因此強(qiáng)制把foh的this綁定到了fohObj上。無(wú)論之后如何調(diào)用函數(shù)baa,它總會(huì)手動(dòng)在fohObj上調(diào)用foh。這種綁定是一種顯示的強(qiáng)制綁定,因此我們稱之為硬綁定。
硬綁定的典型應(yīng)用場(chǎng)景就是創(chuàng)建一個(gè)包裹函數(shù),負(fù)責(zé)接收參數(shù)并返回值。
function foi(something) { console.log(this.a, something); return this.a + something; } var foiObj = { a: 2 } var bae = function() { return foi.apply(foiObj, arguments); } var b = bae(3); console.log(b);
另一種使用方法是創(chuàng)建一個(gè)可以重復(fù)使用的輔助函數(shù)。
function fol(something) { console.log(this.a, something); return this.a + something; } function bind(fn, obj) { return function() { return fn.apply(obj, arguments); } } var folObj = { a: 3 } var bac = bind(fol, folObj); var c = bac(4); console.log(c);
4 new綁定
使用new來調(diào)用函數(shù),或者說發(fā)生構(gòu)造函數(shù)調(diào)用時(shí),會(huì)自動(dòng)執(zhí)行下面的操作。
1) 創(chuàng)建(或者說構(gòu)造)一個(gè)全新的對(duì)象。
2) 這個(gè)新對(duì)象會(huì)被執(zhí)行Prototype連接。
3) 這個(gè)新對(duì)象會(huì)綁定到函數(shù)調(diào)用的this。
4) 如果函數(shù)沒有返回其他對(duì)象,那么new表達(dá)式中的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新對(duì)象。
function abc(a) { this.a = a; } var x = new abc(10); console.log(x.a);
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/79663.html
摘要:關(guān)于的全棉解析上的文章地址判斷函數(shù)是否在中調(diào)用綁定如果是的話綁定的是新創(chuàng)建的對(duì)象。顯而易見,這種方式可能會(huì)導(dǎo)致許多難以分析和追蹤的。默認(rèn)在嚴(yán)格模式下綁定到,否則綁定到全局對(duì)象。 關(guān)于this的全棉解析(上)的文章地址 判斷this 函數(shù)是否在new中調(diào)用(new綁定)?如果是的話this綁定的是新創(chuàng)建的對(duì)象。 bar = new foo() 函數(shù)是否通過call、apply(顯式綁定...
摘要:調(diào)用棧就是為了到達(dá)當(dāng)前執(zhí)行位置所調(diào)用的所有函數(shù)。由于無(wú)法控制回調(diào)函數(shù)的執(zhí)行方式,因此就沒有辦法控制調(diào)用位置得到期望的綁定,下一節(jié)我們會(huì)介紹如何通過固定來修復(fù)這個(gè)問題。 在《你不知道的this》中我們排除了對(duì)于this的錯(cuò)誤理解,并且明白了每個(gè)函數(shù)的this是在調(diào)用時(shí)綁定的,完全取決于函數(shù)的調(diào)用位置。在本節(jié)中我們主要介紹一下幾個(gè)主要內(nèi)容: 什么是調(diào)用位置 綁定規(guī)則 this詞法 調(diào)用...
摘要:在傳統(tǒng)的面向類的語(yǔ)言中,構(gòu)造函數(shù)是類中的一些特殊方法,使用初始化類是會(huì)調(diào)用類中的構(gòu)造函數(shù)。 在上一節(jié)中我們?cè)敿?xì)介紹了this的兩種綁定方式,默認(rèn)綁定和隱式綁定,在這一節(jié)我們繼續(xù)介紹this的另外兩種綁定方式顯示綁定和new綁定。那么,我們要解決的問題當(dāng)然就是上一節(jié)中我們提到的:this丟失! 顯式綁定 在隱式綁定中,我們必須在一個(gè)對(duì)象的內(nèi)部包含一個(gè)指向函數(shù)的屬性,并通過這個(gè)屬性間接引用...
摘要:所以也就是說在沒有的基礎(chǔ)上,執(zhí)行代碼會(huì)在串池中創(chuàng)建一個(gè),也會(huì)在堆內(nèi)存中再出來一個(gè)。不可變性的優(yōu)點(diǎn)安全性字符串不可變安全性的考慮處于兩個(gè)方面,數(shù)據(jù)安全和線程安全。 摘要: String基本特性,String源碼,為什么String不可變? 前言 基于字符串String在java中的地位,關(guān)于String的常識(shí)性知識(shí)就不多做介紹了,我們先來看一段代碼 public class Test {...
摘要:本文就來剖析下什么是是什么在創(chuàng)建代幣一篇,我們講到過代幣,和一樣,同樣是一個(gè)代幣標(biāo)準(zhǔn),官方簡(jiǎn)要解釋是,簡(jiǎn)寫為,多翻譯為非同質(zhì)代幣。返回合約代幣符號(hào),盡管是可選,但強(qiáng)烈建議實(shí)現(xiàn),即便是返回空字符串。 本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接:剖析非同質(zhì)化代幣ERC721-全面解析ERC721標(biāo)準(zhǔn)原文已更新,請(qǐng)讀者前往原文閱讀 什么是ERC-721?現(xiàn)在我們看到的各種加密貓貓狗狗都是基于ERC...
閱讀 3101·2021-11-22 09:34
閱讀 605·2021-11-22 09:34
閱讀 2454·2021-10-08 10:18
閱讀 3387·2021-09-22 15:57
閱讀 2600·2021-09-22 15:25
閱讀 2415·2019-08-30 15:54
閱讀 2127·2019-08-30 15:44
閱讀 1806·2019-08-29 11:18