摘要:使用方法調用匿名函數(shù)在下例中的循環(huán)體內,我們創(chuàng)建了一個匿名函數(shù),然后通過調用該函數(shù)的方法,將每個數(shù)組元素作為指定的值執(zhí)行了那個匿名函數(shù)。這個匿名函數(shù)的主要目的是給每個數(shù)組元素對象添加一個方法,這個方法可以打印出各元素在數(shù)組中的正確索引號。
原文:回味JS基礎:call apply 與 bind
在JavaScript中,call、apply和bind是Function對象自帶的三個方法,本文將通過幾個場景的應用,來詳細理解三個方法。
call()call() 方法在使用一個指定的this值和若干個指定的參數(shù)值的前提下調用某個函數(shù)或方法。
當調用一個函數(shù)時,可以賦值一個不同的 this 對象。this 引用當前對象,即 call 方法的第一個參數(shù)。
通過 call 方法,你可以在一個對象上借用另一個對象上的方法,比如Object.prototype.toString.call([]),就是一個Array對象借用了Object對象上的方法。
thisArg語法 fun.call(thisArg[, arg1[, arg2[, ...]]])
在fun函數(shù)運行時指定的this值。需要注意的是下面幾種情況
(1)不傳,或者傳null,undefined, 函數(shù)中的this指向window對象
(2)傳遞另一個函數(shù)的函數(shù)名,函數(shù)中的this指向這個函數(shù)的引用,并不一定是該函數(shù)執(zhí)行時真正的this值
(3)值為原始值(數(shù)字,字符串,布爾值)的this會指向該原始值的自動包裝對象,如 String、Number、Boolean
(4)傳遞一個對象,函數(shù)中的this指向這個對象
指定的參數(shù)列表。
例子初級應用例子
function a(){ //輸出函數(shù)a中的this對象 console.log(this); } //定義函數(shù)b function b(){} var obj = {name:"這是一個屌絲"}; //定義對象obj a.call(); //window a.call(null); //window a.call(undefined);//window a.call(1); //Number a.call(""); //String a.call(true); //Boolean a.call(b);// function b(){} a.call(obj); //Object
使用call方法調用匿名函數(shù)并且指定上下文的this
在下面的例子中,當調用 greet 方法的時候,該方法的 this 值會綁定到 i對象。
function greet() { var reply = [this.person, "是一個輕量的", this.role].join(" "); console.log(reply); } var i = { person: "JSLite.io", role: "Javascript 庫。" }; greet.call(i); // JSLite.io 是一個輕量的 Javascript 庫。
使用call方法調用匿名函數(shù)
在下例中的for循環(huán)體內,我們創(chuàng)建了一個匿名函數(shù),然后通過調用該函數(shù)的call方法,將每個數(shù)組元素作為指定的this值執(zhí)行了那個匿名函數(shù)。這個匿名函數(shù)的主要目的是給每個數(shù)組元素對象添加一個print方法,這個print方法可以打印出各元素在數(shù)組中的正確索引號。當然,這里不是必須得讓數(shù)組元素作為this值傳入那個匿名函數(shù)(普通參數(shù)就可以),目的是為了演示call的用法。
var animals = [ {species: "Lion", name: "King"}, {species: "Whale", name: "Fail"} ]; for (var i = 0; i < animals.length; i++) { (function (i) { this.print = function () { console.log("#" + i + " " + this.species + ": " + this.name); } this.print(); }).call(animals[i], i); } //#0 Lion: King //#1 Whale: Fail
使用call方法調用函數(shù)傳參數(shù)
var a = { name:"JSLite.io", //定義a的屬性 say:function(){ //定義a的方法 console.log("Hi,I"m function a!"); } }; function b(name){ console.log("Post params: "+ name); console.log("I"m "+ this.name); this.say(); } b.call(a,"test"); //Post params: test //I"m JSLite.io //I"m function a!apply()
語法與 call() 方法的語法幾乎完全相同,唯一的區(qū)別在于,apply的第二個參數(shù)必須是一個包含多個參數(shù)的數(shù)組(或類數(shù)組對象)。apply的這個特性很重要,
在調用一個存在的函數(shù)時,你可以為其指定一個 this 對象。 this 指當前對象,也就是正在調用這個函數(shù)的對象。 使用 apply, 你可以只寫一次這個方法然后在另一個對象中繼承它,而不用在新對象中重復寫該方法。
語法:fun.apply(thisArg[, argsArray])
注意: 需要注意:Chrome 14 以及 Internet Explorer 9 仍然不接受類數(shù)組對象。如果傳入類數(shù)組對象,它們會拋出異常。
參數(shù)thisArg
同上call 的thisArg參數(shù)。
argsArray
一個數(shù)組或者類數(shù)組對象,其中的數(shù)組元素將作為多帶帶的參數(shù)傳給 fun 函數(shù)。如果該參數(shù)的值為null 或 undefined,則表示不需要傳入任何參數(shù)。從ECMAScript 5 開始可以使用類數(shù)組對象。
例子function jsy(x,y,z){ console.log(x,y,z); } jsy.apply(null,[1,2,3]); // 1 2 3
使用apply來鏈接構造器的例子
你可以使用apply來給一個對象鏈接構造器,類似于Java. 在接下來的例子中我們會創(chuàng)建一個叫做construct的全局的Function函數(shù),來使你能夠在構造器中使用一個類數(shù)組對象而非參數(shù)列表。
Function.prototype.construct = function(aArgs) { var fConstructor = this, fNewConstr = function() { fConstructor.apply(this, aArgs); }; fNewConstr.prototype = fConstructor.prototype; return new fNewConstr(); }; function MyConstructor () { for (var nProp = 0; nProp < arguments.length; nProp++) { console.log(arguments,this) this["property" + nProp] = arguments[nProp]; } } var myArray = [4, "Hello world!", false]; var myInstance = MyConstructor.construct(myArray); console.log(myInstance.property1); // logs "Hello world!" console.log(myInstance instanceof MyConstructor); // logs "true" console.log(myInstance.constructor); // logs "MyConstructor"
使用apply和內置函數(shù)
聰明的apply用法允許你在某些本來需要寫成遍歷數(shù)組變量的任務中使用內建的函數(shù)。在接下里的例子中我們會使用Math.max/Math.min來找出一個數(shù)組中的最大/最小值。
//里面有最大最小數(shù)字值的一個數(shù)組對象 var numbers = [5, 6, 2, 3, 7]; /* 使用 Math.min/Math.max 在 apply 中應用 */ var max = Math.max.apply(null, numbers); // 一般情況是用 Math.max(5, 6, ..) 或者 Math.max(numbers[0], ...) 來找最大值 var min = Math.min.apply(null, numbers); //通常情況我們會這樣來找到數(shù)字的最大或者最小值 //比對上面的栗子,是不是下面的看起來沒有上面的舒服呢? max = -Infinity, min = +Infinity; for (var i = 0; i < numbers.length; i++) { if (numbers[i] > max) max = numbers[i]; if (numbers[i] < min) min = numbers[i]; }
參數(shù)數(shù)組切塊后循環(huán)傳入
function minOfArray(arr) { var min = Infinity; var QUANTUM = 32768; for (var i = 0, len = arr.length; i < len; i += QUANTUM) { var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len))); console.log(submin, min) min = Math.min(submin, min); } return min; } var min = minOfArray([5, 6, 2, 3, 7]);bind
bind() 函數(shù)會創(chuàng)建一個新函數(shù)(稱為綁定函數(shù))
bind是ES5新增的一個方法
傳參和call或apply類似
不會執(zhí)行對應的函數(shù),call或apply會自動執(zhí)行對應的函數(shù)
返回對函數(shù)的引用
語法 fun.bind(thisArg[, arg1[, arg2[, ...]]])
下面例子:當點擊網(wǎng)頁時,EventClick被觸發(fā)執(zhí)行,輸出JSLite.io p1 p2, 說明EventClick中的this被bind改變成了obj對象。如果你將EventClick.bind(obj,"p1","p2") 變成 EventClick.call(obj,"p1","p2") 的話,頁面會直接輸出 JSLite.io p1 p2
var obj = {name:"JSLite.io"}; /** * 給document添加click事件監(jiān)聽,并綁定EventClick函數(shù) * 通過bind方法設置EventClick的this為obj,并傳遞參數(shù)p1,p2 */ document.addEventListener("click",EventClick.bind(obj,"p1","p2"),false); //當點擊網(wǎng)頁時觸發(fā)并執(zhí)行 function EventClick(a,b){ console.log( this.name, //JSLite.io a, //p1 b //p2 ) } // JSLite.io p1 p2兼容
if (!Function.prototype.bind) { Function.prototype.bind = function (oThis) { if (typeof this !== "function") { // closest thing possible to the ECMAScript 5 // internal IsCallable function throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, // this在這里指向的是目標函數(shù) fNOP = function () {}, fBound = function () { return fToBind.apply(this instanceof fNOP ? this //此時的this就是new出的obj : oThis || this,//如果傳遞的oThis無效,就將fBound的調用者作為this //將通過bind傳遞的參數(shù)和調用時傳遞的參數(shù)進行合并,并作為最終的參數(shù)傳遞 aArgs.concat(Array.prototype.slice.call(arguments))); }; fNOP.prototype = this.prototype; //將目標函數(shù)的原型對象拷貝到新函數(shù)中,因為目標函數(shù)有可能被當作構造函數(shù)使用 fBound.prototype = new fNOP(); //返回fBond的引用,由外部按需調用 return fBound; }; }
兼容例子來源于:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Compatibility
應用場景:繼承function Animal(name,weight){ this.name = name; this.weight = weight; } function Cat(){ // 在call中將this作為thisArgs參數(shù)傳遞 // Animal方法中的this就指向了Cat中的this // 所以Animal中的this指向的就是cat對象 // 在Animal中定義了name和weight屬性,就相當于在cat中定義了這些屬性 // cat對象便擁有了Animal中定義的屬性,從而達到了繼承的目的 Animal.call(this,"cat","50"); //Animal.apply(this,["cat","50"]); this.say = function(){ console.log("I am " + this.name+",my weight is " + this.weight); } } //當通過new運算符產生了cat時,Cat中的this就指向了cat對象 var cat = new Cat(); cat.say(); //輸出=> I am cat,my weight is 50原型擴展
在原型函數(shù)上擴展和自定義方法,從而不污染原生函數(shù)。例如:我們在 Array 上擴展一個 forEach
function test(){ // 檢測arguments是否為Array的實例 console.log( arguments instanceof Array, //false Array.isArray(arguments) //false ); // 判斷arguments是否有forEach方法 console.log(arguments.forEach); // undefined // 將數(shù)組中的forEach應用到arguments上 Array.prototype.forEach.call(arguments,function(item){ console.log(item); // 1 2 3 4 }); } test(1,2,3,4);
關注公眾號
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78834.html
摘要:為了更好的講解構造函數(shù)原型原型鏈等,我們需要復習一下函數(shù)的一些基礎知識。閉包在復習了函數(shù)的相關基礎知識之后,我們終于可以進入閉包。我們可以這樣理解閉包,首先,閉包是一個函數(shù),是一個什么樣子的函數(shù)呢是一個可以訪問另一個函數(shù)中變量的函數(shù)。 為了更好的講解構造函數(shù)、原型、原型鏈等,我們需要復習一下函數(shù)的一些基礎知識。接下來,就讓我們一起回味一些JS的基礎知識點。 全局變量VS局部變量 簡單粗...
摘要:首先我們可以通過給目標函數(shù)指定作用域來簡單實現(xiàn)方法保存,即調用方法的目標函數(shù)考慮到函數(shù)柯里化的情況,我們可以構建一個更加健壯的這次的方法可以綁定對象,也支持在綁定的時候傳參。原因是,在中,多次是無效的。而則會立即執(zhí)行函數(shù)。 bind 是返回對應函數(shù),便于稍后調用;apply 、call 則是立即調用 。 apply、call 在 javascript 中,call 和 apply 都是...
摘要:返回值這段在下方應用中有詳細的示例解析。回調函數(shù)丟失的解決方案綁定回調函數(shù)的指向這是典型的應用場景綁定指向,用做回調函數(shù)。 showImg(https://segmentfault.com/img/remote/1460000019971331?w=1024&h=680); 函數(shù)原型鏈中的 apply,call 和 bind 方法是 JavaScript 中相當重要的概念,與 this...
摘要:的使用場景作為構造函數(shù)執(zhí)行作為對象屬性執(zhí)行作為普通函數(shù)執(zhí)行。要在執(zhí)行時才能確認值,定義時無法確認改變上下文指向。 1.this this的使用場景: 1.作為構造函數(shù)執(zhí)行; 2.作為對象屬性執(zhí)行; 3.作為普通函數(shù)執(zhí)行; 4.call apply bind。 this要在執(zhí)行時才能確認值,定義時無法確認 var a = { name:A, fn:function()...
摘要:返回的綁定函數(shù)也能使用操作符創(chuàng)建對象這種行為就像把原函數(shù)當成構造器。同時,將第一個參數(shù)以外的其他參數(shù),作為提供給原函數(shù)的預設參數(shù),這也是基本的顆粒化基礎。 今天想談談一道前端面試題,我做面試官的時候經(jīng)常喜歡用它來考察面試者的基礎是否扎實,以及邏輯、思維能力和臨場表現(xiàn),題目是:模擬實現(xiàn)ES5中原生bind函數(shù)。也許這道題目已經(jīng)不再新鮮,部分讀者也會有思路來解答。社區(qū)上關于原生bind的研...
閱讀 588·2023-04-26 01:42
閱讀 3225·2021-11-22 11:56
閱讀 2401·2021-10-08 10:04
閱讀 844·2021-09-24 10:37
閱讀 3128·2019-08-30 15:52
閱讀 1744·2019-08-29 13:44
閱讀 474·2019-08-28 17:51
閱讀 2147·2019-08-26 18:26