国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

this

Airmusic / 2824人閱讀

摘要:全局上下文在全局中,一律指向全局對(duì)象。特殊的以下情況中的需要進(jìn)行特殊記憶。構(gòu)造函數(shù)當(dāng)一個(gè)函數(shù)作為構(gòu)造函數(shù)使用時(shí),構(gòu)造函數(shù)的指向由該構(gòu)造函數(shù)出來(lái)的對(duì)象。舉例使用綁定時(shí),監(jiān)聽(tīng)函數(shù)中的指向觸發(fā)事件的,表示被綁定了監(jiān)聽(tīng)函數(shù)的元素。執(zhí)行與執(zhí)行同理。

我的博客地址 → this | The story of Captain,轉(zhuǎn)載請(qǐng)注明出處。

問(wèn):this 是什么?

答:thiscall 方法的第一個(gè)參數(shù),call 的第一個(gè)參數(shù)就是 this

完。

就這么簡(jiǎn)單么?是的。

為什么這樣說(shuō)?因?yàn)樗械暮瘮?shù)/方法調(diào)用的時(shí)候都可以 轉(zhuǎn)換call 形式,call 的第一個(gè)參數(shù)顯式的指明了函數(shù)該次執(zhí)行時(shí)候的上下文。

今天我們深入探討一下如何確定 this

如何確定 this

this 由函數(shù)的上下文確定。

如何確定“上下文” ?

上下文分為 全局上下文(Global Context) 以及 函數(shù)上下文(Function Context)

全局上下文

在全局中,this 一律指向 全局對(duì)象 window。例如:

console.log(this === window); //; true
函數(shù)上下文

在函數(shù)中,上下文由函數(shù)被調(diào)用的方式?jīng)Q定。

簡(jiǎn)單調(diào)用

以 “函數(shù)名( )” 形式調(diào)用的函數(shù)即為簡(jiǎn)單調(diào)用,簡(jiǎn)單調(diào)用時(shí)上下文為全局上下文,因此 this === window

舉例一:

function foo () {
  console.log(this === window);
}
foo(); // true

舉例二:

function fn1 () {
  function fn2 () {
    console.log(this === window);
  }
  fn2();
}
fn1(); // true,因?yàn)?fn2 為簡(jiǎn)單調(diào)用

舉例三:

let obj = {
  fn1: function () {
    console.log(this === window);
  }
};
let fn2 = obj.fn1; 
fn2(); // true

第三個(gè)例子中,為什么 fn2() 執(zhí)行結(jié)果為 true ?因?yàn)閳?zhí)行了 let fn2 = obj.fn1 之后 fn2 為:

fn2 = function () {
  console.log(this);
}

再執(zhí)行 fn2() 時(shí),為簡(jiǎn)單調(diào)用,因此 this === window

方法調(diào)用

當(dāng)函數(shù)作為一個(gè)對(duì)象的方法被調(diào)用時(shí),this 指向該對(duì)象。

舉例一:

let obj = {
  fn1: function () {
    console.log(this === obj);
  }
};
obj.fn1(); // true

obj.fn1() 形式調(diào)用 fn1 時(shí),是以方法形式調(diào)用的,this 指向該函數(shù)所屬的對(duì)象,即 obj

舉例二:

let obj = {
  fn1: {
    fn2:function () {
      console.log(this === obj.fn1);
    }
  }
};
obj.fn1.fn2(); // true

obj.fn1.fn2() 形式調(diào)用 fn2 時(shí),是以方法形式調(diào)用的,this 指向該函數(shù)所屬的對(duì)象,即 obj.fn1,很多人常誤以為此處的 this 指向 obj,這是錯(cuò)誤的。

舉例三:

let obj = {
  fn1: function () {
    return function () {
      console.log(this === window);
    }
  }
};
let fn2 = obj.fn1();
fn2(); // true

為什么 fn2() 的執(zhí)行結(jié)果為 true ?因?yàn)閳?zhí)行了 let fn2 = obj.fn1() 之后 fn2 為:

fn2 = function () {
  console.log(this === window);
}

再執(zhí)行 fn2() 時(shí),為簡(jiǎn)單調(diào)用,因此 this === window 。如果想要將 fn2 中的 this 指向 obj,可將指向 objthis 保存在中間變量,改動(dòng)如下所示:

let obj = {
  fn1: function () {
    let that = this;
    return function () {
      console.log(that === obj);
    }
  }
};
let fn2 = obj.fn1();
fn2(); // true

利用 let that = thisfn1 中的 this 保存在 that 變量中,然后 fn2() 的結(jié)果即為 true,當(dāng)然這其中涉及到了 閉包(closure) 的知識(shí)。

特殊的 this

以下情況中的 this 需要進(jìn)行特殊記憶。

箭頭函數(shù)

箭頭函數(shù)(arrow function,=>),箭頭函數(shù)為 ES6 中引入的新的函數(shù)表示法,不同之處在于,箭頭函數(shù)中沒(méi)有 this,箭頭函數(shù)中的 this 為其執(zhí)行上下文中的 this,如何理解?舉例說(shuō)明。

舉例一:

() => console.log(this === window); // true

其執(zhí)行上下文為全局上下文,this 指向 window

舉例二:

function foo () {
  return () => console.log(this === window);
};
foo()(); // true

和方法調(diào)用中的舉例三類(lèi)似。

舉例三:

let obj = {
  fn1: () => console.log(this === window);
};
obj.fn1(); // true

為什么是 true ?方法調(diào)用中的舉例一中的 this 不是 obj 嗎?沒(méi)錯(cuò),箭頭函數(shù) fn1 中是沒(méi)有自己的 this 的,因此 this 不指向 obj ,繼續(xù)向上找 obj 的上一級(jí),直到找到有 this 的上下文為止,obj 處在全局上下文中, 全局上下文中有 this,因此箭頭函數(shù)中的 this 為全局上下文中的 this,即 指向 window

舉例四:

let obj = {
  fn1: function () {
    return () => console.log(this === obj);
  }
};
let fn2 = obj.fn1();
fn2(); // true

此處又和方法調(diào)用的舉例三不同,因?yàn)榧^函數(shù)中是沒(méi)有自己的 this 的,箭頭函數(shù)中的 this 為其上一級(jí)的 this ,因此,箭頭函數(shù)中的 this 為其上一級(jí),即 fn1 中的 thisfn1 中的 this 指向 obj,所以箭頭函數(shù)中的 this 指向 obj。根據(jù)箭頭函數(shù)的特性:箭頭函數(shù)中的 this 保留了其上一級(jí)的 this 指向,那么方法調(diào)用舉例三的改動(dòng)可以?xún)?yōu)化為本例所示,用一個(gè)箭頭函數(shù)即可解決,省去了中間變量。

構(gòu)造函數(shù)

當(dāng)一個(gè)函數(shù)作為構(gòu)造函數(shù)使用時(shí),構(gòu)造函數(shù)的 this 指向由該構(gòu)造函數(shù) new 出來(lái)的對(duì)象。舉例說(shuō)明:

function CreateNewPerson (name,gender,age) {
  this.name = name;
  this.gender = gender;
  this.age = age;
}
let me = new CreateNewPerson("daijt","male",18);
console.log(me.name); // "daijt"
console.log(me.gender); // "male"
console.log(me.age); // 18

執(zhí)行 let me = new CreateNewPerson("daijt","male",18) 時(shí),構(gòu)造函數(shù)中的 this 直接指向由其 new 出來(lái)對(duì)象對(duì)象 me ,因此執(zhí)行完該句后 me 的結(jié)構(gòu)如下:

me = {
  name: "daijt",
  gender: "male",
  age: 18
}
原型鏈

舉例一:

let name = new String("daijt");
name.toUpperCase(); // DAIJT

根據(jù)上文構(gòu)造函數(shù)中的 this,執(zhí)行 let name = new String("daijt") 時(shí),String 構(gòu)造函數(shù)中的 this 指向了 name,而 name__proto__ 屬性,該屬性指向所有 string 類(lèi)的共有屬性或者方法,而這些共有的屬性和方法都保存在 String.prototype 中,即:

name.__proto__ === String.prototype; // true

因此 name 是有 toUpperCase 方法的(原型鏈繼承而來(lái)),調(diào)用 toUpperCase 時(shí),toUpperCase 中的 this 指向 name,因此 name.toUpperCase() 的結(jié)果為 DAIJT

舉例二:

let name = "daijt";
name.toUpperCase.(); // DAIJT

為何沒(méi)有通過(guò) new 出來(lái)的對(duì)象也具有 toUpperCase 方法呢?因?yàn)樵趫?zhí)行 let name = "daijt" 的過(guò)程中,JS 有一個(gè)臨時(shí)轉(zhuǎn)化的過(guò)程,例如:

let name = (function (string) {
  return new String(string);
})("daijt");

因此,name 也繼承了 string 類(lèi)共有的屬性和方法,這也算是 JS 的一個(gè)語(yǔ)法糖吧。 當(dāng)然,這涉及到了其他的知識(shí)。

DOM EventHandle

舉例:

let buttons = document.querySelector("button");
buttons.addEventListener("click", function (event) {
  console.log(this === event.currentTarget); // true
});

使用 addEventListener 綁定 DOM 時(shí),監(jiān)聽(tīng)函數(shù)中的 this 指向觸發(fā)事件的 currentTargetcurrentTarget 表示被綁定了監(jiān)聽(tīng)函數(shù)的 DOM 元素。

注意:如果是通過(guò)冒泡觸發(fā)監(jiān)聽(tīng)函數(shù)的話,event.target 不一定等于 event.currentTarget
jQuery EventHandle

HTML:

  • father-ul的第1個(gè)li
  • father-ul的第2個(gè)li
    • son-ul的第1個(gè)li
    • son-ul的第2個(gè)li
    • son-ul的第3個(gè)li
  • father-ul的第3個(gè)li

JavaSctipt:

$("#father-ul").on("click", ".father-li", function (event) {
  console.log(event.target); 
  console.log(event.currentTarget);
  console.log(this === currentTarget);
});

當(dāng)點(diǎn)擊

  • father-ul的第1個(gè)li
  • 時(shí),控制臺(tái)打印出:

  • father-ul的第1個(gè)li
  • father-ul的第1個(gè)li
  • true

    當(dāng)點(diǎn)擊

  • son-ul的第2個(gè)li
  • 時(shí),控制臺(tái)打印出:

  • son-ul的第2個(gè)li
  • father-ul的第2個(gè)li
    • son-ul的第1個(gè)li
    • son-ul的第2個(gè)li
    • son-ul的第3個(gè)li
  • true

    因此可以得出結(jié)論:jQuery EventHandle 中的 this 指的是被代理事件監(jiān)聽(tīng)的 DOM 元素,也就是匹配所有選擇器的 DOM 元素,即 .father-li ,具體解釋可參照 jQuery 文檔 。

    ### 如何改變 this

    以上所述的 this 都為確定的 this,那么如何自己設(shè)置 this,改變 this 的指向呢?或者說(shuō)如何動(dòng)態(tài)改變上下文呢?ES5 為我們提供了三個(gè)全局方法:call()apply()bind()。三個(gè)方法都可以動(dòng)態(tài)的改變上下文,即 this 的指向,三者的區(qū)別可以參照 MDN,以 call() 為例進(jìn)行說(shuō)明。

    var name = "全局上下文";
    let me = {
      name: "daijt",
      gender: "male".
      age: 23,
    };
    let myGirlFriend = {
      name: "xiaofang",
      gender: "female",
      age: 18
    };
    function printName() {
      console.log(this.name);
    }
    printName(); // window
    printName.call(me); // daijt
    printName.call(myGirlFriend); // xiaofang

    執(zhí)行 printName() 時(shí):

    簡(jiǎn)單調(diào)用,因此其內(nèi)部的 this 指向 全局上下文,因此 this === window ,而使用 var 關(guān)鍵字在全局聲明的變量會(huì)作為 window 對(duì)象的屬性,因此 this.name === window.name === 全局上下文

    執(zhí)行 printName.call(me) 時(shí):

    因?yàn)?call() 的第一個(gè)參數(shù)為 thisArg ,因此使用 call() 顯式的指明了 printName 函數(shù)本次執(zhí)行的上下文,即 me,因 this 指向上下文,所以 this === methis.name === me.name === daijt

    執(zhí)行 printName.call(myGirlFriend) 與執(zhí)行 printName.call(me) 同理。

    技巧

    回到本文開(kāi)頭,所有的函數(shù)/方法調(diào)用的時(shí)候都可以 轉(zhuǎn)換call 形式,call 的第一個(gè)參數(shù)顯式的指明了函數(shù)該次執(zhí)行時(shí)候的上下文,這就是判斷 this 指向的技巧,以代碼為例進(jìn)行演示:

    舉例一:

    function foo () {
      console.log(this);
    }
    foo(); // window
    foo.call(); // window
    
    // non-strict mode
    foo.call(undefined); // window
    // strict mode
    foo.call(undefined); // undefined

    foo() 為簡(jiǎn)單調(diào)用,因此 this === window

    foo.call() 中,call() 的第一個(gè)參數(shù)未指明,那么 this === window ,在全局上下文中,非嚴(yán)格模式 下,undefined 即為 window嚴(yán)格模式 下,undefined 不能指代 window ,所以嚴(yán)格模式下 this === undefined

    舉例二:

    let obj = {
      fn1: function () {
        console.log(this === obj);
      }
    };
    obj.fn1(); // true
    obj.fn1.call(obj); // true

    舉例三:

    let obj = {
      fn1: {
        fn2:function () {
          console.log(this === obj.fn1);
        }
      }
    };
    obj.fn1.fn2(); // true
    obj.fn1.fn2.call(obj.fn1); // true

    舉例四:

    let obj = {
      fn1: function () {
        return function () {
          console.log(this === window);
        }
      }
    };
    let fn2 = obj.fn1();
    fn2(); // true
    fn2.call(); // true
    obj.fn1.call(obj).call(undefined); // true

    以上三個(gè)例子中,如何判斷傳給 call()this 呢?以舉例四的最后一句代碼為例進(jìn)行分析:

    通過(guò)這張 call() 的圖解,this 應(yīng)該完全掌握了,所以將函數(shù)的調(diào)用改寫(xiě)為 call() 形式是最直接明了判斷 this 的方法。

    看到這里,你搞懂 this 了嗎?

    參考鏈接:

    this - JavaScript | MDN

    this 的值到底是什么?一次說(shuō)清楚

    你怎么還沒(méi)搞懂 this ?

    更多精彩內(nèi)容,請(qǐng)點(diǎn)擊我的博客 → The story of Captain
    

    文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

    轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/92846.html

    相關(guān)文章

    • node那點(diǎn)事(一) -- Readable streams(可讀流)

      摘要:流的類(lèi)型中有四種基本的流類(lèi)型可讀的流例如可寫(xiě)的流例如可讀寫(xiě)的流例如在讀寫(xiě)過(guò)程中可以修改和變換數(shù)據(jù)的流例如可讀流可讀流有兩種模式流動(dòng)模式可讀流自動(dòng)讀取數(shù)據(jù),通過(guò)接口的事件盡快將數(shù)據(jù)提供給應(yīng)用。 流的簡(jiǎn)介 流(stream)在 Node.js 中是處理流數(shù)據(jù)的抽象接口(abstract interface)。 stream 模塊提供了基礎(chǔ)的 API 。使用這些 API 可以很容易地來(lái)構(gòu)建實(shí)...

      rickchen 評(píng)論0 收藏0
    • 原生js實(shí)現(xiàn)移動(dòng)端+pc端 輪播插件

      摘要:原生寫(xiě)的輪播兼容移動(dòng)端插件,支持輪播速度,輪播內(nèi)容,輪播間隔,手勢(shì)靈敏度自定義,導(dǎo)航圓點(diǎn)點(diǎn)擊跳轉(zhuǎn)手勢(shì)滑動(dòng)。使用說(shuō)明文件包含小部分語(yǔ)法編寫(xiě)的文件,在移動(dòng)端有兼容性問(wèn)題,僅供于源碼參考。移動(dòng)端跟端開(kāi)發(fā)引用文件直接下載進(jìn)行引入使用。 slide.js 原生js寫(xiě)的輪播兼容 pc+移動(dòng)端 插件,支持輪播速度,輪播內(nèi)容,輪播間隔,手勢(shì)靈敏度自定義,導(dǎo)航圓點(diǎn)點(diǎn)擊跳轉(zhuǎn),手勢(shì)滑動(dòng)。 使用說(shuō)明:sli...

      leanxi 評(píng)論0 收藏0
    • 手把手教你用原生JavaScript造輪子(2)——輪播圖(更新:ES6版本)

      摘要:綁定輪播事件然后是鼠標(biāo)移入移出事件的綁定鼠標(biāo)移入移出事件移入時(shí)停止輪播播放的定時(shí)器,移出后自動(dòng)開(kāi)始下一張的播放。 通過(guò)上一篇文章的學(xué)習(xí),我們基本掌握了一個(gè)輪子的封裝和開(kāi)發(fā)流程。那么這次將帶大家開(kāi)發(fā)一個(gè)更有難度的項(xiàng)目——輪播圖,希望能進(jìn)一步加深大家對(duì)于面向?qū)ο蟛寮_(kāi)發(fā)的理解和認(rèn)識(shí)。 So, Lets begin! 目前項(xiàng)目使用 ES5及UMD 規(guī)范封裝,所以在前端暫時(shí)只支持標(biāo)簽的引入方式...

      jasperyang 評(píng)論0 收藏0
    • 基本數(shù)據(jù)結(jié)構(gòu)和查找算法

      摘要:本文包括簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu)和查找算法,屬于個(gè)人整理。初學(xué)編程可以用這里的東西聯(lián)系一下,看一看也挺有意思博主個(gè)人不認(rèn)為中算法數(shù)據(jù)結(jié)構(gòu)不重要,畢竟這是程序開(kāi)發(fā)的基本功。 本文包括簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu)和查找算法,屬于個(gè)人整理。初學(xué)編程可以用這里的東西聯(lián)系一下,看一看也挺有意思博主個(gè)人不認(rèn)為js中算法數(shù)據(jù)結(jié)構(gòu)不重要,畢竟這是程序開(kāi)發(fā)的基本功。本文還會(huì)根據(jù)博主學(xué)習(xí)進(jìn)展和時(shí)間安排不定期更新 數(shù)據(jù)結(jié)構(gòu)部分 列...

      姘擱『 評(píng)論0 收藏0
    • ionic 2+ 手勢(shì)解鎖界面

      摘要:手勢(shì)解鎖界面一些對(duì)安全要求比較高的少不了鎖屏頁(yè)面,而手勢(shì)解鎖對(duì)于用戶(hù)來(lái)說(shuō)使用方便,對(duì)于程序員來(lái)說(shuō)小有挑戰(zhàn),怎么有棄之不用的道理。 ionic 2+ 手勢(shì)解鎖界面 一些對(duì)安全要求比較高的app少不了鎖屏頁(yè)面,而手勢(shì)解鎖對(duì)于用戶(hù)來(lái)說(shuō)使用方便,對(duì)于程序員來(lái)說(shuō)小有挑戰(zhàn),怎么有棄之不用的道理。 效果圖 效果圖處理短,方便大家閱讀showImg(https://segmentfault.co...

      Hancock_Xu 評(píng)論0 收藏0

    發(fā)表評(píng)論

    0條評(píng)論

    最新活動(dòng)
    閱讀需要支付1元查看
    <