摘要:文章盡量使用大量實(shí)例進(jìn)行講解,它們的使用場(chǎng)景。在嚴(yán)格模式下,函數(shù)被調(diào)用后,里面的默認(rèn)是后面通過(guò)調(diào)用函數(shù)上的和方法,該變指向,函數(shù)里面的指向。利用,可以傳入外層的上下文。同樣適用的還有,里面的對(duì)象,它也是一種類(lèi)數(shù)組對(duì)象。
call,apply and bind in JavaScript
在ECMAScript中,每個(gè)函數(shù)都包含兩個(gè)繼承而來(lái)的方法:apply() 和 call(),這兩個(gè)方法的用途都是在特定的作用域中調(diào)用函數(shù),主要作用跟bind一樣,用來(lái)改變函數(shù)體內(nèi)this的指向,或者說(shuō)是在函數(shù)調(diào)用時(shí)改變上下文。
文章盡量使用大量實(shí)例進(jìn)行講解,它們的使用場(chǎng)景。同時(shí),也會(huì)由淺入深的引導(dǎo)出一些理論,畢竟這幾個(gè)常用方法,在MDN上都能找到合理的解釋
基本功能 改變this的指向var fruit = { fruitName:"apple" } function getFruit() { console.log("I like "+this.fruitName) } getFruit(); // log I like undefined getFruit.call(fruit) // log I like apple getFruit.apply(fruit) // log I like apple var newBind = getFruit.bind(fruit) newBind(); // log I like apple
當(dāng) getFruit 并非作為一個(gè)對(duì)象的屬性,而是直接當(dāng)做一個(gè)函數(shù)來(lái)調(diào)用,里面的this就會(huì)被綁定到全局對(duì)象上,即window上, 所以直接調(diào)用 getFruit,里面的this指向了全局對(duì)象上,返回 undefined。
在嚴(yán)格模式下,函數(shù)被調(diào)用后,里面的this默認(rèn)是 undefined
后面,通過(guò)調(diào)用函數(shù)上的call和apply方法,該變this指向,函數(shù)里面的this指向fruit。
區(qū)別:
bind同樣實(shí)現(xiàn)了改變this指向的功能,但是它不會(huì)立即執(zhí)行,而是會(huì)重新創(chuàng)建一個(gè)綁定函數(shù),新函數(shù)被調(diào)用時(shí),使用bind()方法里面的第一個(gè)參數(shù)作為this
這三個(gè)方法,從接受的第二參數(shù)開(kāi)始,都直接傳遞給函數(shù),但是接受參數(shù)的方法卻很大的不同。
call,從第二個(gè)參數(shù)開(kāi)始,以參數(shù)列表的形式展示,
apply,則把傳遞的函數(shù)參數(shù),放在一個(gè)數(shù)組里面作為第二個(gè)參數(shù)。
fn.call(obj,arg1,arg2); fn.apply(obj,[arg1,arg2])
bind,從第二個(gè)參數(shù)開(kāi)始,同樣以參數(shù)列表的形式,但是會(huì)提前放在新綁定函數(shù)的參數(shù)之前
var foo = function(name,age){ console.log("name: "+name+"- age: "+age) } var p1 = foo.bind(this,"popo"); // "popo" 作為新函數(shù)的第一個(gè)參數(shù)。 p1(13); // logs name: popo- age: 13 p1("bobo",14) // logs name: popo- age: bobo應(yīng)用場(chǎng)景
綁定事件回調(diào)中
$(".div-class").on("click",function(event) { /*TODO*/ }.bind(this)); } }
通常,我們?cè)诟淖兒瘮?shù)上下文之前,都會(huì)使用類(lèi)似that = this,或者self,_this,來(lái)把this賦值給一個(gè)變量。利用.bind(),可以傳入外層的上下文。
循環(huán)回調(diào)
循環(huán)中利用閉包來(lái)處理回調(diào)
for(var i = 0;i < 10;i++){ (function(j){ setTimeout(function(){ console.log(j); },600); })(i) }
每次循環(huán),都會(huì)產(chǎn)生一個(gè)立即執(zhí)行的函數(shù),函數(shù)內(nèi)部的局部變量j保存不同時(shí)期i的值,循環(huán)過(guò)程中,setTimeout回調(diào)按順序放入消息隊(duì)列中,等f(wàn)or循環(huán)結(jié)束后,堆棧中沒(méi)有同步的代碼,就去消息隊(duì)列中,執(zhí)行對(duì)應(yīng)的回調(diào),打印出j的值。
同理,可以利用bind,每次都創(chuàng)建新的函數(shù),并且已經(jīng)預(yù)先設(shè)置了參數(shù),傳入不同的指針
function func(i) { console.log(i) } for(var i =0 ;i< 10;i++) { setTimeout(func.bind(null,i),600) }
實(shí)現(xiàn)繼承
var Person = function(name,age) { this.name = name; this.age = age; } var P1 = function(name,age) { // 借用構(gòu)造函數(shù)的方式實(shí)現(xiàn)繼承 // 利用call 繼承了Person Person.call(this,name,age) } P1.prototype.getName = function() { console.log("name: "+this.name+", age: "+this.age); } var newPerson = new P1("popo",20); // logs name: popo, age: 20 newPerson.getName();
實(shí)質(zhì)上,可以看成通過(guò)call()或者apply()方法,在即將新建的對(duì)象,即這里的newPerson上,執(zhí)行超類(lèi)型的構(gòu)造函數(shù),分別在當(dāng)前上下文this上添加name和age屬性。
數(shù)組驗(yàn)證的終極方法
function isArray(value) { return Object.prototype.toString.call(value) == "[object Array]" }
借用了Object原生的toString()方法,打印出對(duì)應(yīng)變量的構(gòu)造函數(shù)名,
類(lèi)數(shù)組轉(zhuǎn)換為數(shù)組
// 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的數(shù)組 "unshift"方法 Array.prototype.unshift = function(){ this.splice.apply(this, [0,0].concat(Array.prototype.slice.apply(arguments))); return this.length; }
首先,利用this.splice.apply(),其中splice,可以直接從數(shù)組中移除或者插入變量。apply()則以數(shù)組的形式傳遞參數(shù),需要利用concat拼接數(shù)組。
當(dāng)函數(shù)被調(diào)用時(shí),在函數(shù)內(nèi)部會(huì)得到類(lèi)數(shù)組arguments,它擁有一個(gè)length屬性,但是沒(méi)有任何數(shù)組的方法。所以,將slice方法中的this指向arguments,獲取到arguments的長(zhǎng)度,從而確定方法的start和end下標(biāo),得到一個(gè)數(shù)組變量。
同樣適用的還有,DOM里面的NodeList對(duì)象,它也是一種類(lèi)數(shù)組對(duì)象。
深入理解 實(shí)現(xiàn)bind 方法bind方法在ECMAScript5里面被引入,前面提到過(guò),調(diào)用該方法時(shí),返回一個(gè)新的函數(shù),可以簡(jiǎn)單使用下面方法實(shí)現(xiàn)其改變this指向的功能。
Function.prototype.bind = function(scope) { var fn = this; return function() { return fn.apply(scope) } }
接著,就可以利用concat把bind傳遞的預(yù)置參數(shù)拼接到新函數(shù)的參數(shù)列表中。
Function.prototype.bind = function(scope) { var args = Array.prototype.slice.call(arguments,1) var fn = this return function() { return fn.apply(scope,args.concat(Array.prototype.slice.call(arguments))) } }
參考鏈接
Javascript之bind
Understanding JavaScript Bind ()
深入淺出妙用 Javascript 中 apply、call、bind
前端基礎(chǔ)進(jìn)階:全方位解讀 this
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/93371.html
摘要:理解文章中已經(jīng)比較全面的分析了在中的指向問(wèn)題,用一句話來(lái)總結(jié)就是的指向一定是在執(zhí)行時(shí)決定的,指向被調(diào)用函數(shù)的對(duì)象。與和直接執(zhí)行原函數(shù)不同的是,返回的是一個(gè)新函數(shù)。這個(gè)新函數(shù)包裹了原函數(shù),并且綁定了的指向?yàn)閭魅氲摹? 理解 JavaScript this 文章中已經(jīng)比較全面的分析了 this 在 JavaScript 中的指向問(wèn)題,用一句話來(lái)總結(jié)就是:this 的指向一定是在執(zhí)行時(shí)決定的,...
摘要:關(guān)于在絕大多數(shù)情況下,函數(shù)的調(diào)用方式?jīng)Q定了的值。不能在執(zhí)行期間被賦值,并且在每次函數(shù)被調(diào)用時(shí)的值也可能會(huì)不同。它們除了參數(shù)略有不同,其功能完全一樣。它們的第一個(gè)參數(shù)都為將要指向的對(duì)象。 關(guān)于 this 在絕大多數(shù)情況下,函數(shù)的調(diào)用方式?jīng)Q定了this的值。this不能在執(zhí)行期間被賦值,并且在每次函數(shù)被調(diào)用時(shí)this的值也可能會(huì)不同。 全局 this window.something = ...
摘要:閉包閉包的概念與詞法域關(guān)系緊密。閉包甚至在函數(shù)已經(jīng)返回后也可以獲取其外部函數(shù)的變量。一種常見(jiàn)的閉包導(dǎo)致的由立即調(diào)用函數(shù)表達(dá)式解決的例子事實(shí)上結(jié)果的所有都是,而不是按順序得出的,。 介紹 JavaScript 有一個(gè)特征————作用域。理解作用域scope可以使你的代碼脫穎而出,減少錯(cuò)誤,幫助你用它構(gòu)造強(qiáng)大的設(shè)計(jì)模式。 什么是作用域 作用域就是在代碼執(zhí)行期間變量,函數(shù)和對(duì)象能被獲取到的特...
I thought I know the Function definition, execution context and the behavior of this in JavaScript. However, I realized that actually I dont or the knowlege is still not firmly grounded in my mind wh...
摘要:至于,其只是以數(shù)組的方傳入?yún)?shù),其它部分是一樣的,如下它們也可用于在中的類(lèi)繼承中,調(diào)用父級(jí)構(gòu)造器。間接調(diào)用,調(diào)用了父級(jí)構(gòu)造器對(duì)比方法和,它倆都立即執(zhí)行了函數(shù),而函數(shù)返回了一個(gè)新方法,綁定了預(yù)先指定好的,并可以延后調(diào)用。 其實(shí)this是一個(gè)老生常談的問(wèn)題了。關(guān)于this的文章非常多,其實(shí)我本以為自己早弄明白了它,不過(guò)昨天在做項(xiàng)目的過(guò)程中,還是出現(xiàn)了一絲疑惑,想到大概之前在JavaScri...
閱讀 569·2023-04-26 02:58
閱讀 2309·2021-09-27 14:01
閱讀 3616·2021-09-22 15:57
閱讀 1175·2019-08-30 15:56
閱讀 1049·2019-08-30 15:53
閱讀 796·2019-08-30 15:52
閱讀 651·2019-08-26 14:01
閱讀 2167·2019-08-26 13:41