js中的this

// 默認綁定
// 在沒有其他規則使用時的默認綁定
// function foo(){
//  console.log(this.a);
// }
// var a = 2;
// foo();

// 隱含綁定
// 調用點是否為一個環境對象,也叫作擁有者或者容器
// function foo(){
//  console.log( this.a );
// };
// var obj = {
//  a: 2,
//  b: 3,
//  fooo: foo,
// };
// obj.fooo();
// foo()被聲明后作為引用屬性添加到obj上,被obj擁有或者包含,所以this指代的是obj


// 隱含的丟失
// 隱含綁定丟失了他的綁定,這就意味著它要退回到默認綁定
// function foo() {
//  console.log(this.a);
// };
// var obj = {
//  a: 2,
//  fooo: foo,
// };
// var bar = obj.fooo;
// var a = 3;
// bar();

// 接下來我們考慮一下傳遞一個回調函數
// function foo(){
//  console.log(this.a);
// };
// function doFoo(fn){
//  fn();
// };
// var obj = {
//  a: 2,
//  fooo: foo,
// };
// var a = 3;

// doFoo(obj.fooo);

// 明確綁定
// 隱含綁定: 我們不得不改變目標對象使它自身包含一個對函數的引用,而后使用這個函數引用屬性來間接的,將this綁定到這個對象上。
// 明確綁定: 我們強制一個函數調用使用某個特定的對象作為this綁定

// function foo(){
//  console.log(this.a);
// };
// var obj = {
//  a: 2,
// };
// foo.call( obj );

// 當然我們也可以傳遞原始的類型值(string boolean number),這個類型值會被包裝在他的對象類型中,new String() new Number()...

// function sum(){
//  // console.log(this+2);  chai boxing
//  console.log(this); //boxing
// };
// sum.call(5);


// 硬綁定
// 有時候,單獨依靠明確綁定仍然不能為我們先前提到的問題提供解決方案,也就是函數丟失原本的this綁定,或者被第三方框架覆蓋,等問題。

// function foo(){
//  console.log(this.a);
// };
// var obj = {
//  a: 2,
// };
// var bar = function(){
//  foo.call( obj );
// };
// var a = 3;
// bar();
// bar.call(window);//不會被覆蓋


// 用硬綁定將一個函數包裝起來的最典型的方法,是為所有傳入的參數和傳出的返回值創建一個通道

// function foo(something){
//  console.log(this.a , something);
//  return this.a + something;
// };
// var obj = {
//  a: 2,
// };
// var bar = function(){
//  return foo.apply( obj,arguments );
// };
// var b = bar( 3 );
// console.log( b );

// 由于硬綁定是一個非常常用的模式,它已作為ES5中的內建工具提供:
// Function.prototype.bind

// 如下使用
// function foo(something){
//  console.log(this.a,something);
//  return this.a + something;
// };
// var obj = {
//  a: 2,
// };
// var bar = foo.bind(obj);
// var b = bar( 3 );
// console.log( b );

// new 綁定  
// js中構造器的定義:構造器僅僅是一個函數,它們偶然的被前置的new操作符調用,它們不依附于類,它們也不初始化類,它們本質上只是一般的函數,在被使用new來調用時改變了行為。

// 當在函數前面被加入new調用時,也就是構造器調用時,下面這些事情會自動完成
// 1.一個全新的對象會憑空創建 
// 2.這個新構建的對象會被接入原型鏈(prototype-linked)
// 3.這個新構建的對象被設置為函數調用的this綁定
// 4.除非函數返回一個它自己的其他對象,這個被new調用的函數將自動返回這個新構建的對象。


// 綁定的順序
// 函數中的this綁定規則的優先級

// function foo() {
//     console.log( this.a );
// }

// var obj1 = {
//     a: 2,
//     foo: foo
// };

// var obj2 = {
//     a: 3,
//     foo: foo
// };

// obj1.foo(); // 2
// obj2.foo(); // 3

// obj1.foo.call( obj2 ); // 3
// obj2.foo.call( obj1 ); // 2

// =====得出結論===>明確綁定 的優先權要高于 隱含綁定

// function foo(something) {
//     this.a = something;
// }

// var obj1 = {
//     foo: foo
// };

// var obj2 = {};

// obj1.foo( 2 );
// console.log( obj1.a ); // 2

// obj1.foo.call( obj2, 3 );
// console.log( obj2.a ); // 3

// var bar = new obj1.foo( 4 );
// console.log( obj1.a ); // 2
// console.log( bar.a ); // 4

// =====得出結論===>new綁定 的優先級要高于 隱含綁定


// 總結this
// 現在,我們可以按照優先順序來總結一下this的規則。

// 1.new 綁定
// 2.硬綁定
// 3.明確綁定
// 4.隱含綁定
// 5.默認綁定

// 以上,就是理解對于普通的函數調用來說的this綁定規則所需的全部。

// 當然還有一些特殊的特例

// 如果你傳遞null或undefined作為call,apply或bind的this綁定參數,那么這些值會被忽略掉,取而代之的是 默認綁定 規則將適用于這個調用。

// function foo() {

//     console.log( this.a );
//     console.log( this );
// }
// var a = 2;
// foo.call( null ); 


// 擴展
// 詞法this   簡單來說就是用一個變量保存this
// 我們剛剛涵蓋了一般函數遵守的4種規則。但是ES6引入了一種不適用于這些規則特殊的函數:箭頭函數(arrow-function)。

// 最后,復習一下
// 為執行中的函數判定this綁定需要找到這個函數的直接調用點。找到之后,4種規則將會以 這個 優先順序施用于調用點:

/*
    1、被new調用?使用新構建的對象。
    2、被call或apply(或 bind)調用?使用指定的對象。
    3、被持有調用的環境對象調用?使用那個環境對象。
    4、默認:strict mode下是undefined,否則就是全局對象。
*/
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容