關(guān)于this的幾種情況以及call漓摩、apply的區(qū)別使用

關(guān)于THIS的幾種情況 :

  • 給當(dāng)前元素的某個(gè)事件行為綁定方法隅忿,方法中的THIS是當(dāng)前元素本身「排除:DOM2在IE6~8中基于attachEvent進(jìn)行事件綁定,這樣處理方法中的this->window」
  • 方法執(zhí)行征堪,看方法前面是否有“點(diǎn)”瘩缆,有“點(diǎn)”,“點(diǎn)”前面是誰THIS就是誰佃蚜,沒有“點(diǎn)”,THIS是window「嚴(yán)格模式下是undefiend」,特殊例外:

自執(zhí)行函數(shù)中的THIS一般是window/undefined
回調(diào)函數(shù)中的THIS一般是window/undefined「當(dāng)然某些方法中會(huì)做一些特殊的處理」
括號(hào)表達(dá)式有特殊性
........

  • 構(gòu)造函數(shù)執(zhí)行咳榜,構(gòu)造函數(shù)體中的THIS是當(dāng)前類的實(shí)例
  • 箭頭函數(shù)中沒有THIS「類似的還有塊級(jí)上下文」,所以無論怎樣去執(zhí)行爽锥,怎樣去修改涌韩,都沒有用,如果函數(shù)中出現(xiàn)THIS氯夷,一定是其所在的上級(jí)上下文中的THIS
  • 在Function.prototype提供了三個(gè)方法:call/apply/bind臣樱,這三個(gè)方法都是用來強(qiáng)制改變函數(shù)中this指向的「每一個(gè)函數(shù)都是Function的實(shí)例,所以都可以調(diào)取這三個(gè)方法執(zhí)行」

代碼:

"use strict";
let obj = {
    name: 'zhufeng',
    fn() {
        /!* // this -> obj
        let self = this;
        setTimeout(function () {
            // console.log(this);
            // this -> window
            console.log(self);
        }, 1000); *!/

        setTimeout(() => {
            console.log(this);
            // this是上級(jí)上下文中的,也就是obj
        }, 1000);
    }
}
obj.fn();

call/apply/bind 三者的區(qū)別:

需求:把fn函數(shù)執(zhí)行腮考,并且讓方法中的this是obj雇毫,再并且傳遞10/20分別給x和y形參

"use strict";
window.name = 'window';
const fn = function fn(x, y) {
    console.log(this, x + y);
};
let obj = {
    name: 'obj'
};
// fn(); //this->undefined  Uncaught TypeError: Cannot read property 'name' of undefined
// obj.fn(); //Uncaught TypeError: obj.fn is not a function  obj中不存在fn屬性,之間沒有關(guān)聯(lián)


fn.call(obj, 10, 20);

fn.call(); //fn中的this->window/undefined  x=undefined  y=undefined
fn.call(null/undefined); //this->window & null/undefined  x=undefined  y=undefined
fn.call(10, 20); //this->10  x=20  y=undefined


fn.apply(obj, [10, 20]); 

fn首先作為Function的實(shí)例,基于proto找到Function.prototype.call方法踩蔚,并且把找到的call方法執(zhí)行.


apply和call只有一個(gè)區(qū)別:

call方法在設(shè)定給函數(shù)傳遞的實(shí)參信息的時(shí)候棚放,是要求一個(gè)個(gè)傳遞實(shí)參值;但是apply是要求用戶把所有需要傳遞的實(shí)參信息以數(shù)組/類數(shù)組進(jìn)行管理的馅闽; 雖然要求這樣寫飘蚯,但是內(nèi)部最后處理的時(shí)候馍迄,和call一樣,也是一項(xiàng)項(xiàng)的傳遞給函數(shù)的局骤;

場景一:求一個(gè)數(shù)組中的最大值或者最小值

let arr = [10, 14, 23, 34, 20, 13];

// 1.排序處理 時(shí)間復(fù)雜度稍微高一些「sort內(nèi)部 N^2」
console.log(arr.sort((a, b) => b - a)[0]); 
// 2.假設(shè)法  N
let max = arr[0],
    i = 1,
    len = arr.length,
    item;
for (; i < len; i++) {
    item = arr[i];
    if (item > max) {
        max = item;
    }
}
console.log(max); 
//3.Math.max獲取最大值  推薦

console.log(Math.max(10, 14, 23, 34, 20, 13)); //=>34
console.log(Math.max(arr)); //=>NaN  方法本身是獲取一堆數(shù)字中的最大值攀圈,需要把比較的數(shù)字一項(xiàng)項(xiàng)的傳遞給max方法才可以

// 想把數(shù)組中的每一項(xiàng)分別傳遞給max方法
let max = Math.max(...arr);
console.log(max); //=>34

let max = Math.max.apply(null, arr); //利用apply的機(jī)制「雖然傳遞給apply的是一個(gè)數(shù)組,但是apply內(nèi)部會(huì)把數(shù)組中的每一項(xiàng)分別傳遞給對(duì)應(yīng)的函數(shù)」峦甩;而且Math.max中用不到this赘来,所以this改成誰無所謂,就是占個(gè)位而已凯傲;
console.log(max); //=>34

場景二:任意數(shù)求和「不確定實(shí)參的個(gè)數(shù)犬辰,所以無法基于設(shè)定形參接受」

  + 剩余運(yùn)算符 ES6
  + arguments ES3
const sum = function sum(...params) {
    if (params.length === 0) return 0;
    // params -> 數(shù)組
    return params.reduce((total, item) => total + item, 0);
}; 
const sum = function sum() {
    let params = arguments; // params -> 類數(shù)組「不能直接使用數(shù)組的辦法」
    if (params.length === 0) return 0;
    // 把類數(shù)組轉(zhuǎn)換為數(shù)組
    //   + params = Array.from(params);  ES6+
    //   + params = [...params]; ES6+
    //   + ...
    let i = 0,
        len = params.length,
        arr = [];
    for (; i < len; i++) {
        arr[arr.length] = params[i]; //<==> arr.push(params[i]);
    }
    return arr.reduce((total, item) => total + item, 0);
}; 
Array.prototype.slice = function slice() {
    // 模擬的方法
    // this -> ary
    let i = 0,
        len = this.length,
        arr = [];
    for (; i < len; i++) {
        arr[arr.length] = this[i];
    }
    return arr;
};
// ary.slice()
// ary.slice(0)
// // 數(shù)組的克隆,把原始數(shù)組中的每一項(xiàng)都克隆一份給返回的新數(shù)組「淺克隆」

const sum = function sum() {
    let params = arguments;
    if (params.length === 0) return 0;
    params = [].slice.call(params);
    return params.reduce((total, item) => total + item, 0);
};

把類數(shù)組轉(zhuǎn)換為數(shù)組:如果我們能把slice執(zhí)行冰单,并且讓slice中的this是arguments幌缝,這樣就相當(dāng)于在迭代arguments中的每一項(xiàng),把每一項(xiàng)賦值給新的數(shù)組集合 -> 也就是把類數(shù)組轉(zhuǎn)換為數(shù)組
+ 如何讓slice執(zhí)行 Array.prototype.slice() / [].slice() .....
+ 如何改變slice中的this call/apply...

原理:“因?yàn)轭悢?shù)組的結(jié)果和數(shù)組非常的相似”球凰,所以大部分操作數(shù)組的代碼狮腿,也同樣適用于類數(shù)組,在這個(gè)前提下呕诉,我們只需要把實(shí)現(xiàn)好的數(shù)組方法執(zhí)行缘厢,讓方法中的this變?yōu)轭愃平M,就相當(dāng)于類數(shù)組在操作這寫代碼甩挫,實(shí)現(xiàn)了類數(shù)組借用數(shù)組方法的目的贴硫,我們這種操作叫做“鴨子類型”


 const sum = function sum() {
    let params = arguments;
    if (params.length === 0) return 0;
    // 不轉(zhuǎn)換了,直接借用即可
    return [].reduce.call(params, (total, item) => total + item, 0);
}


const sum = function sum() {
    let params = arguments;
    // params.__proto__ = Array.prototype; //修改原型鏈的指向  arguments可以直接使用數(shù)組原型上的任何方法
    params.reduce = Array.prototype.reduce;
    if (params.length === 0) return 0;
    return params.reduce((total, item) => total + item, 0);
};

console.log(sum()); //->0
console.log(sum(10)); //->10
console.log(sum(10, 20)); //->30
console.log(sum(10, 20, 30)); //->60
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末伊者,一起剝皮案震驚了整個(gè)濱河市英遭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌亦渗,老刑警劉巖挖诸,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異法精,居然都是意外死亡多律,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門搂蜓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狼荞,“玉大人,你說我怎么就攤上這事帮碰∠辔叮” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵殉挽,是天一觀的道長丰涉。 經(jīng)常有香客問我拓巧,道長,這世上最難降的妖魔是什么昔搂? 我笑而不...
    開封第一講書人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任玲销,我火速辦了婚禮输拇,結(jié)果婚禮上摘符,老公的妹妹穿的比我還像新娘。我一直安慰自己逛裤,他們只是感情好猴抹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開白布跋理。 她就那樣靜靜地躺著前普,像睡著了一般骡湖。 火紅的嫁衣襯著肌膚如雪响蕴。 梳的紋絲不亂的頭發(fā)上浦夷,一...
    開封第一講書人閱讀 51,521評(píng)論 1 304
  • 那天誓禁,我揣著相機(jī)與錄音辫继,去河邊找鬼姑宽。 笑死舵变,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼秆吵,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼纳寂!你這毒婦竟也來了毙芜?” 一聲冷哼從身側(cè)響起晦雨,我...
    開封第一講書人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤奥邮,失蹤者是張志新(化名)和其女友劉穎脚粟,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體团南,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年堕担,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了已慢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片曲聂。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡霹购,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出朋腋,到底是詐尸還是另有隱情齐疙,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布旭咽,位于F島的核電站贞奋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏穷绵。R本人自食惡果不足惜轿塔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望仲墨。 院中可真熱鬧勾缭,春花似錦、人聲如沸目养。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽癌蚁。三九已至幻梯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間努释,已是汗流浹背碘梢。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留伐蒂,地道東北人煞躬。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像饿自,于是被迫代替她去往敵國和親汰翠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子龄坪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

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