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

資訊專欄INFORMATION COLUMN

this

Airmusic / 2837人閱讀

摘要:全局上下文在全局中,一律指向全局對象。特殊的以下情況中的需要進行特殊記憶。構造函數當一個函數作為構造函數使用時,構造函數的指向由該構造函數出來的對象。舉例使用綁定時,監聽函數中的指向觸發事件的,表示被綁定了監聽函數的元素。執行與執行同理。

我的博客地址 → this | The story of Captain,轉載請注明出處。

問:this 是什么?

答:thiscall 方法的第一個參數,call 的第一個參數就是 this

完。

就這么簡單么?是的。

為什么這樣說?因為所有的函數/方法調用的時候都可以 轉換call 形式,call 的第一個參數顯式的指明了函數該次執行時候的上下文。

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

如何確定 this

this 由函數的上下文確定。

如何確定“上下文” ?

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

全局上下文

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

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

在函數中,上下文由函數被調用的方式決定。

簡單調用

以 “函數名( )” 形式調用的函數即為簡單調用,簡單調用時上下文為全局上下文,因此 this === window

舉例一:

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

舉例二:

function fn1 () {
  function fn2 () {
    console.log(this === window);
  }
  fn2();
}
fn1(); // true,因為 fn2 為簡單調用

舉例三:

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

第三個例子中,為什么 fn2() 執行結果為 true ?因為執行了 let fn2 = obj.fn1 之后 fn2 為:

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

再執行 fn2() 時,為簡單調用,因此 this === window

方法調用

當函數作為一個對象的方法被調用時,this 指向該對象。

舉例一:

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

obj.fn1() 形式調用 fn1 時,是以方法形式調用的,this 指向該函數所屬的對象,即 obj

舉例二:

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

obj.fn1.fn2() 形式調用 fn2 時,是以方法形式調用的,this 指向該函數所屬的對象,即 obj.fn1,很多人常誤以為此處的 this 指向 obj,這是錯誤的。

舉例三:

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

為什么 fn2() 的執行結果為 true ?因為執行了 let fn2 = obj.fn1() 之后 fn2 為:

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

再執行 fn2() 時,為簡單調用,因此 this === window 。如果想要將 fn2 中的 this 指向 obj,可將指向 objthis 保存在中間變量,改動如下所示:

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() 的結果即為 true,當然這其中涉及到了 閉包(closure) 的知識。

特殊的 this

以下情況中的 this 需要進行特殊記憶。

箭頭函數

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

舉例一:

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

其執行上下文為全局上下文,this 指向 window

舉例二:

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

和方法調用中的舉例三類似。

舉例三:

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

為什么是 true ?方法調用中的舉例一中的 this 不是 obj 嗎?沒錯,箭頭函數 fn1 中是沒有自己的 this 的,因此 this 不指向 obj ,繼續向上找 obj 的上一級,直到找到有 this 的上下文為止,obj 處在全局上下文中, 全局上下文中有 this,因此箭頭函數中的 this 為全局上下文中的 this,即 指向 window

舉例四:

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

此處又和方法調用的舉例三不同,因為箭頭函數中是沒有自己的 this 的,箭頭函數中的 this 為其上一級的 this ,因此,箭頭函數中的 this 為其上一級,即 fn1 中的 thisfn1 中的 this 指向 obj,所以箭頭函數中的 this 指向 obj。根據箭頭函數的特性:箭頭函數中的 this 保留了其上一級的 this 指向,那么方法調用舉例三的改動可以優化為本例所示,用一個箭頭函數即可解決,省去了中間變量。

構造函數

當一個函數作為構造函數使用時,構造函數的 this 指向由該構造函數 new 出來的對象。舉例說明:

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

執行 let me = new CreateNewPerson("daijt","male",18) 時,構造函數中的 this 直接指向由其 new 出來對象對象 me ,因此執行完該句后 me 的結構如下:

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

舉例一:

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

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

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

因此 name 是有 toUpperCase 方法的(原型鏈繼承而來),調用 toUpperCase 時,toUpperCase 中的 this 指向 name,因此 name.toUpperCase() 的結果為 DAIJT

舉例二:

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

為何沒有通過 new 出來的對象也具有 toUpperCase 方法呢?因為在執行 let name = "daijt" 的過程中,JS 有一個臨時轉化的過程,例如:

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

因此,name 也繼承了 string 類共有的屬性和方法,這也算是 JS 的一個語法糖吧。 當然,這涉及到了其他的知識。

DOM EventHandle

舉例:

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

使用 addEventListener 綁定 DOM 時,監聽函數中的 this 指向觸發事件的 currentTargetcurrentTarget 表示被綁定了監聽函數的 DOM 元素。

注意:如果是通過冒泡觸發監聽函數的話,event.target 不一定等于 event.currentTarget
jQuery EventHandle

HTML:

  • father-ul的第1個li
  • father-ul的第2個li
    • son-ul的第1個li
    • son-ul的第2個li
    • son-ul的第3個li
  • father-ul的第3個li

JavaSctipt:

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

當點擊

  • father-ul的第1個li
  • 時,控制臺打印出:

  • father-ul的第1個li
  • father-ul的第1個li
  • true

    當點擊

  • son-ul的第2個li
  • 時,控制臺打印出:

  • son-ul的第2個li
  • father-ul的第2個li
    • son-ul的第1個li
    • son-ul的第2個li
    • son-ul的第3個li
  • true

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

    ### 如何改變 this

    以上所述的 this 都為確定的 this,那么如何自己設置 this,改變 this 的指向呢?或者說如何動態改變上下文呢?ES5 為我們提供了三個全局方法:call()apply()bind()。三個方法都可以動態的改變上下文,即 this 的指向,三者的區別可以參照 MDN,以 call() 為例進行說明。

    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

    執行 printName() 時:

    簡單調用,因此其內部的 this 指向 全局上下文,因此 this === window ,而使用 var 關鍵字在全局聲明的變量會作為 window 對象的屬性,因此 this.name === window.name === 全局上下文

    執行 printName.call(me) 時:

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

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

    技巧

    回到本文開頭,所有的函數/方法調用的時候都可以 轉換call 形式,call 的第一個參數顯式的指明了函數該次執行時候的上下文,這就是判斷 this 指向的技巧,以代碼為例進行演示:

    舉例一:

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

    foo() 為簡單調用,因此 this === window

    foo.call() 中,call() 的第一個參數未指明,那么 this === window ,在全局上下文中,非嚴格模式 下,undefined 即為 window嚴格模式 下,undefined 不能指代 window ,所以嚴格模式下 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

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

    通過這張 call() 的圖解,this 應該完全掌握了,所以將函數的調用改寫為 call() 形式是最直接明了判斷 this 的方法。

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

    參考鏈接:

    this - JavaScript | MDN

    this 的值到底是什么?一次說清楚

    你怎么還沒搞懂 this ?

    更多精彩內容,請點擊我的博客 → The story of Captain
    

    文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

    轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/92846.html

    相關文章

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

      摘要:流的類型中有四種基本的流類型可讀的流例如可寫的流例如可讀寫的流例如在讀寫過程中可以修改和變換數據的流例如可讀流可讀流有兩種模式流動模式可讀流自動讀取數據,通過接口的事件盡快將數據提供給應用。 流的簡介 流(stream)在 Node.js 中是處理流數據的抽象接口(abstract interface)。 stream 模塊提供了基礎的 API 。使用這些 API 可以很容易地來構建實...

      rickchen 評論0 收藏0
    • 原生js實現移動端+pc端 輪播插件

      摘要:原生寫的輪播兼容移動端插件,支持輪播速度,輪播內容,輪播間隔,手勢靈敏度自定義,導航圓點點擊跳轉手勢滑動。使用說明文件包含小部分語法編寫的文件,在移動端有兼容性問題,僅供于源碼參考。移動端跟端開發引用文件直接下載進行引入使用。 slide.js 原生js寫的輪播兼容 pc+移動端 插件,支持輪播速度,輪播內容,輪播間隔,手勢靈敏度自定義,導航圓點點擊跳轉,手勢滑動。 使用說明:sli...

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

      摘要:綁定輪播事件然后是鼠標移入移出事件的綁定鼠標移入移出事件移入時停止輪播播放的定時器,移出后自動開始下一張的播放。 通過上一篇文章的學習,我們基本掌握了一個輪子的封裝和開發流程。那么這次將帶大家開發一個更有難度的項目——輪播圖,希望能進一步加深大家對于面向對象插件開發的理解和認識。 So, Lets begin! 目前項目使用 ES5及UMD 規范封裝,所以在前端暫時只支持標簽的引入方式...

      jasperyang 評論0 收藏0
    • 基本數據結構和查找算法

      摘要:本文包括簡單的數據結構和查找算法,屬于個人整理。初學編程可以用這里的東西聯系一下,看一看也挺有意思博主個人不認為中算法數據結構不重要,畢竟這是程序開發的基本功。 本文包括簡單的數據結構和查找算法,屬于個人整理。初學編程可以用這里的東西聯系一下,看一看也挺有意思博主個人不認為js中算法數據結構不重要,畢竟這是程序開發的基本功。本文還會根據博主學習進展和時間安排不定期更新 數據結構部分 列...

      姘擱『 評論0 收藏0
    • ionic 2+ 手勢解鎖界面

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

      Hancock_Xu 評論0 收藏0

    發表評論

    0條評論

    最新活動
    閱讀需要支付1元查看
    <