第2章this、call和apply

第2章this霹肝、call和apply

2.1 this

2.1.1 this的去向

1作為對象方法調(diào)用

var obj = {
    a:1,
    getA:function(){
        console.log(this === obj);  //true
        console.log(this.a); //1
    }
}
obj.getA();

2作為普通函數(shù)調(diào)用

//瀏覽器
window.name = 'globalName'

var getName = function(){
    return this.name;
}

console.log(getName()); //globalName

//或者

window.name = 'globalName'

var myObject = {
    name:'sven',
    getName:function(){
        return this.name;
    }
}
var getName = myObject.getName;
console.log(getName());  //globalName

<!DOCTYPE html>
<html lang="en">

<body>
    <div id="div1">我是一個div</div>
    <script>
        window.id = 'window';
        document.getElementById('div1').onclick = function(){
            alert(this.id); //div1
            var callback = function(){
                alert(this.id);  //window
            }
            callback();//被作為普通函數(shù)調(diào)用
        }
    </script>   

</body>
</html>

保存div結(jié)點(diǎn)的引用

document.getElementById('div1').onclick = function(){
    var that = this;
    var callback = function(){
    alert(this.id);  //div1
    }
    callback();
}

es5的strict模式下叉袍,這種情況下的this已經(jīng)被規(guī)定為不會指向全局對象,而是undefined

function func() {
    'use strict'
    alert(this); //undefined
}
func

3構(gòu)造器調(diào)用

var Mycalss = function(){
    this.name = 'sven'
    return 'anne';
}
var obj = new Mycalss();
alert(obj.name);  //sven

顯式地返回一個object類型

var Mycalss = function(){
    this.name = 'sven';
    return {
        name:'anne'
    }
}
var obj = new Mycalss();
alert(obj.name);  //anne

4Function.prototype.call或者Function.prototype.apply調(diào)用可以動態(tài)傳入函數(shù)this

var ob1 = {
    name:'sven',
    getName:function(){
        return this.name;
    }
}
var obj2 = {
    name:'anne'
}
console.log(obj1.getName());//sven
console.log(obj1.getName(obj2));//anne

2.1.2丟失的this

var myObject = {
    name:'sven',
    getName:function(){
        return this.name;
    }
}
console.log(myObject.getName());//sven
var getName2 = myObject.getName;
console.log(getName2());//undefined

<html>
    <body>
        <div id="div1">我是一個div</div>
    </body>
    <script>
        var getId = document.getElementById;
        getId('div1'); //異常
    </script>
</html>


document.getElementById = (function(func){
    return function(){
        return func.apply(document,arguments);
    }
})(document.getElementById);
var getId = document.getElementById;
var div = getId('div1');
alert(div.id);  //div1

2.2call和apply

2.2.1call和apply的區(qū)別

apply接受兩個參數(shù)叨橱,第一個參數(shù)指定了函數(shù)體內(nèi)的this對象的指向典蜕,第二個參數(shù)為一個帶下標(biāo)的集合,這個集合可以為數(shù)組罗洗,也可以為類數(shù)組愉舔,apply方法把集合中的元素作為參數(shù)傳遞給被調(diào)用的函數(shù):

var func = function(a,b,c){
    alert([a,b,c]); //[1,2,3]
}
func.apply(null,[1,2,3]);

call傳入的參數(shù)不固定,跟apply相同的是伙菜,第一個參數(shù)也是代表函數(shù)體內(nèi)的this指向轩缤,從第二個參數(shù)開始往后,每個參數(shù)被依次傳人函數(shù)

var func = function(a,b,c){
    alert([a,b,c]); //[1,2,3]
}
func.call(null,1,2,3);

call是包裝在apply上面的語法糖,明確知道函數(shù)接受多少參數(shù)火的,而且想一目了然的表達(dá)形參與實(shí)參的對應(yīng)關(guān)系壶愤,那么也可以用call來傳遞參數(shù)。

當(dāng)使用call和apply的時候馏鹤,如果我們傳人的第一個參數(shù)為null征椒,函數(shù)體內(nèi)的this會指向默認(rèn)的宿主對象,在瀏覽器中則是window:

var func = function(a,b,c){
    alert(this == window); //true
}
func.call(null,1,2,3);

嚴(yán)格模式還是null

var func = function(a,b,c){
    alert(this === null); //true
}
func.call(null,1,2,3);

傳人null來代替某個具體的對象

Math.max.apply(null,[1,2,3,5,4])  //5

2.2.2call和apply的用途

1改變this指向
var obj1 = {
name:'sven'
}

var obj2 = {
    name:'anne'
}

window.name = 'window'
var getName = function(){
    alert(this.name);
}
getName();
getName.call(obj1);
getName.call(obj2);


document.getElementById('div1').onclick = function(){
    var func = function(){
        alert(this.id)  //div1
    }
    func.call(this);
}

2Function.prototype.bind

Function.prototype.bind = function(content){
    var self = this;
    return function(){
        return self.apply(context,arguments);
    }
};
var obj = {
    name:'sven'
}
var func = function(){
    alert(this.name); //sven
}.bind(obj);
func();

復(fù)雜

Function.prototype.bind = function(){
    var self = this,
        context = [].shift.call(arguments),
        args = [].slice.call(arguments);
    return function(){
        return self.apply(context,[].concat.call(args,[].slice.call(arguments)));
    }
};
var obj = {
    name:'sven'
}
var func = function(a,b,c,d){
    console.log(this.name); //sven
    console.log([a,b,c,d]); //[1,2,3,4]
}.bind(obj,1,2);
func(3,4);

3借用其他對象的方法

var A = function(name){
    this.name = name;
}
var B = function(){
    A.apply(this,arguments);
}
B.proto.getName = function(){
    return this.name;
}
var b = new B('sven');
console.log(b.getName()) //sven

往arguments中添加一個新的元素湃累,通常會借用Array.prototype.push:

(function(){
    Array.prototype.push.call(arguments,3);
    console.log(arguments); //[1,2,3]
})(1,2)

arguments轉(zhuǎn)成真正的數(shù)組Array.prototype.slice;
截去頭一個元素Array.prototype.shift;

V8引擎源碼Array.prototype.push

function ArrayPush(){
    var n = TO_UINT32(this.length); //被push的對象的length
    var m = %_ArgumentsLength(); //push的參數(shù)個數(shù)
    for(var i = 0; i < m; i++){
        this[i+n] = %_Arguments(i); //復(fù)制元素
    }
    this.length = n + m;
    return this.length;
}

對象是數(shù)組還是類數(shù)組一點(diǎn)都不重要勃救,可以把“任意”對象傳人

var a = {}
Array.prototype.push.call(a,'first');
alert(a.length);//1
alert(a[0]); //first

在低版本IE瀏覽器中執(zhí)行,必須顯式地給對象a設(shè)置length屬性

var a = {
  length:0
};

對象本身要可以存取屬性
對象的length屬性可讀寫

var a = 1;
Array.prototype.push.call(a.'first');
alert(a.length);//undefined
alert(a[0]);//undefined

var func = function(){};
Array.prototype.push.call(func,'first');
alert(func.length)//報(bào)錯
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末治力,一起剝皮案震驚了整個濱河市蒙秒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宵统,老刑警劉巖晕讲,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異马澈,居然都是意外死亡瓢省,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進(jìn)店門痊班,熙熙樓的掌柜王于貴愁眉苦臉地迎上來净捅,“玉大人,你說我怎么就攤上這事辩块。” “怎么了荆永?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵废亭,是天一觀的道長。 經(jīng)常有香客問我具钥,道長豆村,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任骂删,我火速辦了婚禮掌动,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宁玫。我一直安慰自己粗恢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布欧瘪。 她就那樣靜靜地躺著眷射,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上妖碉,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天涌庭,我揣著相機(jī)與錄音,去河邊找鬼欧宜。 笑死坐榆,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的冗茸。 我是一名探鬼主播席镀,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼赎瞎,長吁一口氣:“原來是場噩夢啊……” “哼耐朴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碧信,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤麻蹋,失蹤者是張志新(化名)和其女友劉穎跛溉,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扮授,經(jīng)...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡芳室,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了刹勃。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堪侯。...
    茶點(diǎn)故事閱讀 40,973評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖荔仁,靈堂內(nèi)的尸體忽然破棺而出伍宦,到底是詐尸還是另有隱情,我是刑警寧澤乏梁,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布次洼,位于F島的核電站,受9級特大地震影響遇骑,放射性物質(zhì)發(fā)生泄漏卖毁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一落萎、第九天 我趴在偏房一處隱蔽的房頂上張望亥啦。 院中可真熱鬧,春花似錦练链、人聲如沸翔脱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽碍侦。三九已至粱坤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瓷产,已是汗流浹背站玄。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留濒旦,地道東北人株旷。 一個月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像尔邓,于是被迫代替她去往敵國和親晾剖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,241評論 0 4
  • 在JavaScript編程中循头,this關(guān)鍵字總是讓初學(xué)者感到迷惑,F(xiàn)unction.prototype.call和...
    白小蟲閱讀 410評論 0 1
  • 本文源于本人關(guān)于《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》(曾探著)的閱讀總結(jié)。想詳細(xì)了解具體內(nèi)容建議閱讀該書形入。 ...
    yozosann閱讀 268評論 0 1
  • 特別說明亿遂,為便于查閱浓若,文章轉(zhuǎn)自https://github.com/getify/You-Dont-Know-JS...
    殺破狼real閱讀 697評論 0 1
  • 今天主要講了窗體的高級應(yīng)用,列表框蛇数、組合框控件的應(yīng)用七嫌。下午做了相應(yīng)的習(xí)題。 做自己嗯苞慢!
    34d71ddb735c閱讀 175評論 0 0