动态

详情 返回 返回

this 指針詳解 - 动态 详情

概念

this 是當前函數/當前模塊的運行環境上下文。是一個指針型變量,普通函數中的 this 是在調用時才被綁定確認指向的。

通過不同的 this 調用同一個函數,可以產生不同的結果。

到底如何確認 this 綁定的內容是什麼?

this 綁定的規則

1.默認綁定

function a() {}
a();

函數獨立調用的時候,不帶任何修飾的函數引用.

  • 非嚴格模式下 this 指向全局對象
var a = 'hello';
var obj = {
    a: 'world',
    foo: function () {
        console.log(this.a);
    },
};

let bar = obj.foo;
bar(); // hello 在調用的時候是直接調用的。所以是指向全局的this
// obj.foo(); // world
  • 嚴格模式下,this 指向 undefined,嚴格模式下,不允許指向全局對象。
var a = 'hello';
var obj = {
    a: 'world',
    foo: function () {
        'use strict';
        console.log(this.a);
    },
};

let bar = obj.foo;
bar(); // 會報錯因為this是指向的undefined
  • 普通函數作為參數傳遞的情況,setTimeOut,setInterval, 非嚴格模式下 this 指向全局對象。
var name = 'hello';

var person = {
    name: 'world',
    sayHi: sayHi,
};

function sayHi() {
    console.log(this); // person
    setTimeout(function () {
        // 指向了全局對象
        console.log(this.name); // hello
    });
}

person.sayHi();

2.隱式綁定

與默認綁定相反,函數調用的時候有顯式的修飾,

var a = 'hello';
var obj = {
    a: 'world',
    foo: function () {
        console.log(this.a);
    },
};

// 誰調用 這個函數(foo)誰就是這個函數的this
obj.foo();
  • 在鏈式調用的情況下,this 就近指向
function sayHi() {
    console.log(this.name);
}

var person1 = {
    name: 'hello',
    sayHi: sayHi,
};

var person2 = {
    name: 'world',
    friend: person1,
};

// 鏈式調用的時候是就近指向
person2.friend.sayHi();

顯式綁定

call apply bind 可以修改函數的 this 指向

call 和 apply 的異同

  • 都是改變 this 指向,然後執行原有函數
  • 第一個參數都是作為 this 的,綁定到函數體的 this 上,如果不傳參數 fun.cal() , 非嚴格模式下,this 會綁定到全局對象
func.call(this, arg1, arg2, ..., argn);
func.apply(this, [arg1, ..., argn])
// 只有object tostring 可以返回類型
Object.prototype.toString.call(obj) === '[object Array]'
  • 如果 call 的第一個參數,傳了數字或者字符串等基本類型 會發生什麼?
    得到字符串的對象,數字的對象 [Number: 1] [String: 'lubai'] 等

bind

bind 方法,會創建一個新的函數,
當這個新函數被調用的時候,bind 的第一個參數會作為函數運行時的 this,之後的一系列參數都會在傳遞實參前傳入作為它的函數.

var account = {
    name: 'hello',
    author: 'world',
    subscribe: function (subsc) {
        console.log(`${subsc} ${this.name}`);
    },
};
account.subscribe('微言'); // 微言 hello
var subsc1 = account.subscribe.bind({ name: 'name', author: 'author' }, 'subsc');
subsc1(); // subsc name (顯式綁定的優先級,比隱式綁定的優先級高)

new

  1. 創建一個空對象
  2. 將空對象的\_\_proto\_\_指向原型對象的 prototype
  3. 以新對象為 this 執行原有的構造函數
  4. return
function Study(name) {
    this.name = name;
}

var study = new Study('hello');

console.log(study.name);

5. this 綁定的優先級

new 綁定 > 顯式(bind, call, apply)綁定 > 隱式綁定(obj.foo()) > 默認綁定(foo())

// 顯式綁定的優先級,比隱式綁定高
function foo(a) {
    // console.log(this.a);
    this.a = a;
}

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

var obj2 = {
    a: 3,
    foo: foo,
};
// 隱式綁定
obj1.foo(); // 2
obj2.foo(); //3

// 將this的指向進行強行更改
obj1.foo.call(obj2); // 3
obj2.foo.call(obj1); // 2
function foo(a) {
    // console.log(this.a);
    this.a = a;
}
var obj1 = {
    foo: foo,
};

var obj2 = {};

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

// 強行把foo的參數指向了obj2上
obj1.foo.call(obj2, 3);
console.log(obj2.a); // 3

// new 將obj1指向bar 相當於 bar.a = a, 並不會改變obj1這個對象
var bar = new obj1.foo(4);

console.log(obj1.a); // 2
console.log(bar.a); // 4
function foo(a) {
    this.a = a;
}
var obj1 = {};

// bind 執行的this改變成obj1
var bar = foo.bind(obj1);

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

var barNew = new bar(3);
// new的過程中,以新對象為this運行原來的構造函數 function foo(a) {this.a = a}
// 新對象是 barNew

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

console.log(barNew.a); // 3

箭頭函數

  1. 箭頭函數沒有arguments
  2. 箭頭函數沒有構造函數 (本身沒有constructor)
  3. 沒有自己的this (this的指向是由定義箭頭函數的位置決定的,而普通函數是調用的時候才確定的)

題目練習

  1. 題目1

    var a = 123;
    function getA() {
     console.log(this.a) // undefined
    }
    
    getA()
var a = 123;
var obj = {
    a: 456,
    getA: function() {

        // console.log(this)  這裏的this指向obj
        function getAA() { // 裏面有獨立的this
            console.log(this.a) // undefined
        }
        getAA() // 默認綁定
    }
}
obj.getA() // undefined
  1. 題目2

    var length = 10;
    function fn() {
     console.log(this.length)
    }
    var obj = {
     length: 5,
     method: function(fn) {
         // this = obj
         // fn 是一個參數,以函數為參數的 this 指向全局。
         fn();  10
    
         // arguments{0:fn, 1: 1, length:2} 相當於隱式綁定綁定到了fn對象上
         arguments[0]()
     }
    }
    obj.method(fn, 1)
user avatar tianmiaogongzuoshi_5ca47d59bef41 头像 cyzf 头像 zaotalk 头像 smalike 头像 nihaojob 头像 jingdongkeji 头像 kobe_fans_zxc 头像 dirackeeko 头像 aqiongbei 头像 chongdianqishi 头像 longlong688 头像 dunizb 头像
点赞 114 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.