摘要:的指向除去不常用的和,的指向大致可分為以下四種作為對象的方法調用作為普通函數調用構造器調用或調用作為對象的方法調用當函數作為對象的方法被調用時,指向該對象。
this
和其他語言不同,JavaScript的this總是指向一個對象,而具體指向哪個對象是在運行時基于函數的執行環境動態綁定的,而非函數被聲明時的環境。
this的指向除去不常用的with和eval,this的指向大致可分為以下四種:
作為對象的方法調用
作為普通函數調用
構造器調用
Function.prototype.call或Function.prototype.apply調用
作為對象的方法調用當函數作為對象的方法被調用時,this指向該對象。
var obj={ a:1, getA:function(){ alert(this===obj);//true alert(this.a);//1 } }; obj.getA();作為普通函數調用
當函數不作為對象的屬性被調用時,也就是普通函數方式,此時this總是指向全局對象。在瀏覽器中,這個全局對象是window。
window.name="globalName"; var getName1=function(){ return this.name; }; var myObject={ name:"sven", getName:function(){ return this.name; } }; var getName=myObject.getName; alert(getName1());//globalName alert(getName());//globalName構造器調用
當用new運算符調用函數時,該函數總會返回一個對象,通常情況下,構造器里的this就指向返回的這個對象。
var MyClass=function(){ this.name="sven"; }; var obj=new MyClass(); alert(obj.name);//sven
但是如果構造器顯式地返回了一個object類型的對象,那么此次運算結果最終會返回這個對象,而不是我們之前期待的this:
var MyClass=function(){ this.name="sven"; return{ name:"anne"; } }; var obj=new MyClass(); alert(obj.name);//anne
如果構造器不顯式地返回任何數據,或者是返回一個非對象類型的數據,就不會造成上述問題:
var MyClass=function(){ this.name="sven"; return "anne"; }; var obj=new MyClass(); alert(obj.name);//svencall和apply調用
call和apply可以動態的地改變傳入函數的this:
var obj1={ name:"sven", getName:function(){ return this.name; } }; var obj2={ name:"anne" }; console.log(obj1.getName()); console.log(obj1.getName.call(obj2));call和apply
call和apply作用一模一樣,區別在于傳入參數的形式不同。apply接受兩個參數,第一個參數指定了函數體內this對象的指向,第二個參數第二個參數為一個帶下標的集合,這個集合可以為數組,也可以為類數組。
JavaScript的參數在內部就是用一個數組來表示的,從這個意義上來說,apply比call的使用率更高。call是包裝在apply上的一顆語法糖,如果我們明確知道函數接受多少個參數,而且想一目了然地表達形參和實參的對應關系,那么也可以用call來傳送參數。
當使用call或者apply時,如果我們傳入的第一個參數是null,函數體內的this會指向默認的宿主對象,在瀏覽器中就是window,但如果是在嚴格模式下,函數體內的this還是為null。
有時候我們使用call或者apply的目的并不在于指定this的指向,而是另有用途,比如借用其他對象的方法,那么我們就可以傳入null來代替某個具體的對象。
call和apply的用途 改變this的指向 Function.prototype.bindFunction.prototype.bind=function() { var self=this, context=[].shift.call(arguments),//需要綁定的this上下文 args=[].slice.call(arguments);//剩余的參數轉成數組 return function(){ return self.apply(context,[].concat.call(args,[].slice.call(arguments)));//執行新的函數體的時候,會把之前傳入的context當作新函數體內的this,并且組合兩次分別傳入的參數,作為新函數的參數 } }; var obj={ name:"sven" }; var func=function(a,b,c,d){ alert(this.name); alert([a,b,c,d]); }.bind(obj,1,2); func(3,4);使用其他對象的方法
第一種場景是借用構造函數,可以實現一些類似繼承的效果:
var A=function(name){ this.name=name; }; var B=function(){ A.apply(this,arguments); }; B.prototype.getName=function(){ return this.name; }; var b=new B("sven"); console.log(b.getName());
第二種場景:函數的參數列表arguments是一個類數組對象,雖然它也有下標,但她并非真正的數組,所以不能進行排序操作或者往集合里添加一個新的元素。這種情況下我們常常會借用Array.prototype對象上的方法。比如想往arguments里插入一個元素,通常會借用Array.prototype.push:
(function(){Array.prototype.push.call(arguments,3)})(1,2);
在操作arguments時,我們經常非常頻繁地找Array.prototype借用方法。
轉化為數組:Array.prototype.slice
截去頭元素:Array.prototype.shift
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/86282.html
摘要:參數和是放在數組中傳入函數,分別對應參數的列表元素。而原函數中的并沒有被改變,依舊指向全局對象。保存原函數保存需要綁定的上下文剩余的參數轉為數組返回一個新函數下一篇介紹閉包中閉包的詳解。 apply 和 call 的區別 ECMAScript 規范給所有函數都定義了 call 與 apply 兩個方法,它們的應用非常廣泛,它們的作用也是一模一樣,只是傳參的形式有區別而已。 apply(...
摘要:第二行將函數的指向一個字符串第三行將函數的指向一個數字以此類推。再舉一個例子實現對象繼承繼承了的屬性和方法陳安東男姓名年齡性別輸出姓名陳安東年齡性別男這樣用就實現了繼承用也類似 這里排版不是太好,詳情看我的簡書 經過網上的大量搜索,漸漸明白了apply()和call方法的使用,為此寫一篇文章記錄一下。 定義 apply()方法: Function.apply(obj,args)obj:...
摘要:也就是說當使用后,當前執行上下文中的對象已被替換為,后續執行將以所持有的狀態屬性繼續執行。借用的方法替換的實例去調用相應的方法。實現引用類型的繼承其實沒有類這一概念,我們平時使用的等嚴格來說被稱作引用類型。 call 方法:object.method.call(targetObj[, argv1, argv2, .....]) apply 方法:object.method.apply(...
摘要:當沒有使用而直接調用時指向對象函數和函數非常的相似,第一個參數都用來設置目標函數運行時的指向。輸出的結果為結果證明兩個地方傳入的參數都會被傳給目標函數,函數拷貝調用時傳入的參數會追加在函數調用時傳入的參數后面。 call() , apply() 與 bind() 詳解 我們知道可以用call(), apply() 和 bind()這三個函數都是用來完成函數調用,并且設置this指向。 ...
閱讀 2627·2021-11-17 17:00
閱讀 1881·2021-10-11 10:57
閱讀 3750·2021-09-09 11:33
閱讀 918·2021-09-09 09:33
閱讀 3555·2019-08-30 14:20
閱讀 3321·2019-08-29 11:25
閱讀 2804·2019-08-26 13:48
閱讀 745·2019-08-26 11:52