1. 程式人生 > >JavaScript中this指向問題

JavaScript中this指向問題

this是在執行時繫結的。函式呼叫方式的不同就可能使this所繫結的物件不同

一.幾種繫結規則

Ⅰ.預設繫結

  • 一般情況下,若無其他規則出現則預設將this繫結到全域性物件上
function foo(){
    var a = 3;
    console.log(a);
}
var a = 2;
foo();      //2

//foo()在呼叫時使用不帶任何修飾的函式引用,只能使用預設繫結
  • this常有的集中錯誤理解之一就是認為this指向當前函式的詞法作用域

  • this與詞法作用域及作用域物件是完全不同的東西

Ⅱ.隱式繫結

  • 若在呼叫位置有上下文物件(可理解為此函式呼叫時使用一個物件.出來的),就遵循隱式繫結
function foo(){
    console.log(a);
}
var obj = {a:2, foo:foo};
var a = "opps,global";  //全域性物件的屬性
obj.foo();              //2     隱式繫結
var bar = obj.foo;      //這裡進行了一次引用賦值
bar();                  //opps,global

如果細心的話你會發現,上邊的程式碼出現了一個問題:隱式丟失

  • 當進行隱式繫結時,如果進行一次引用賦值或者傳參操作,會造成this的丟失,使this繫結到全域性物件中去。

由於第7行處進行了以此引用賦值,所以造成了bar()不具有上下文物件,故系統會自動採取預設繫結規則

我們再來舉一個傳參操作造成隱式丟失的例子

function foo(){
    console.log(this.a);
}
function doFoo(fn){
    fn();               //在此呼叫時引數傳遞為隱式賦值,丟失this繫結
}
var obj = {a:2, foo:foo};
var a = "opps,global";
doFoo(obj.foo);         //看似為隱式繫結,但輸出的是opps,global  

所以我們需要記住:函式傳遞就是一種隱式賦值,而隱式賦值會造成隱式丟失

同樣,js中的一些內建函式在接受一個函式作為引數時恩惠發生以上情況

function setTimeout(fn, delay){
    //等待delay毫秒數
    fn();
}

Ⅲ.顯式繫結

使用apply和call為要執行的函式直接繫結this稱為顯式繫結

function foo(){
    console.log(this.a);
}
var obj = {a:2};
foo.call(obj);      //2
  • PS:
    • 若給call/apply傳入的是一個基本型別資料,則這個基本型別資料將被轉換成對應的基本包裝型別
    • 此種方法仍然無法解決繫結丟失問題
1.硬繫結
function foo(){
    console.log(this.a);
}
var obj = {a:2};
var bar = function(){       //建立一個包裹函式以確保obj的繫結
    foo.call(obj);
};
bar();                      //2
setTimeout(bar, 1000);      //時隔一秒列印2
bar.call(window);           //2

通過此方法(包裹函式)可以確保obj的繫結,不過韓式不能為函式傳參

function foo(something){
    console.log(this.a, something);
    return this.a + something;
}

function bind(fn, obj){     //輔助繫結函式
    return function(){
        return fn.apply(obj, arguments);
    };
}

var obj = {a:2};
var bar = bind(foo, obj);
var b = bar(3);
console.log(b);

//2 3
//5
  • ES5中內建了bind方法(其實就是個語法糖)。其返回一個硬編碼的新函式,將你制定的物件繫結到呼叫它的函式的this上
function foo(something){
    console.log(this.a, something);
    return this.a + something;
}

function bind(fn, obj){     //輔助繫結函式
    return function(){
        return fn.apply(obj, arguments);
    };
}

var obj = {a:2};
var bar = foo.bind(obj);    //bind返回一個繫結到obj上的新函式
var b = bar(3);
console.log(b);
var a = "window's a";
foo("!");               //對原來的函式不產生影響


//2 3
//15 5
//window's a !
//"window's a!"
6.API呼叫引數指定this
function foo(e1){
    console.log(e1, this.id);
}
var obj = {id:"Sir"};
[1,2,3].forEach(foo, obj);      //forEach第二個引數用來設定this


//1 "Sir"
//2 "Sir"
//3 "Sir"

Ⅳ.new繫結

function foo(){
    this.a = 1;
    this.b = 2;
}
var instance = new foo();
console.log(instance.a);
發生函式的構造呼叫時自動執行以下操作
  • 建立一個全新的物件
  • 此物件會被執行[[Prototype]]連結
  • 此新物件會繫結到函式呼叫的this(new繫結)
  • 執行此函式程式碼
  • 若函式無返回值,則自動返回此新物件

Ⅴ.箭頭函式的this

function foo(){
    return (a)=>{
        console.log(this.a);
    }
}
var obj1 = {a:2};
var obj2 = {a:3};
var bar = foo.apply(obj1);
bar.apply(obj2);        //2
  • 箭頭函式是ES6中的語法。無法使用以上幾種規則。
  • 其根據外層的作用域來決定this
  • 箭頭函式的繫結無法修改,new繫結也不行

相關推薦

javascriptthis指向的理解(轉載)

       JS中的this指向一直是個讓人頭疼的問題,想當初我學的是天昏地暗,查了好多資料,看的頭都大了,跟他大戰了那麼多回合,終於把它搞定個七八分,其實往往都是我們複雜化了,現在就讓大家輕鬆看懂this的指向,我會分以下幾種情況來說。 this的指向: &nb

JavaScriptthis指向

JavaScript中this的四大判定: 1.預設繫結this指向window: example: function test (c){ var a = 123; function b(){

JavaScriptthis指向問題

this是在執行時繫結的。函式呼叫方式的不同就可能使this所繫結的物件不同 一.幾種繫結規則 Ⅰ.預設繫結 一般情況下,若無其他規則出現則預設將this繫結到全域性物件上 function foo(){ var a = 3;

JavaScriptthis關鍵字的指向問題

asc 函數調用 javascrip new spa con oba cti func 1、純粹的函數調用,this就代表全局對象Global var x = 1; function test(){ var x = ‘二哈‘; console.log(th

javascriptthis指向

span this 有時 變量 mage bsp 匿名函數 javascrip 生成 作為一個前端小白在開發中對於this的指向問題有時候總是會模糊,於是花時間研究了一番。 首先this是JS的關鍵字,this是js函數在運行是生成的一個內部對象,生成的這個this只能在函

第149天:javascriptthis指向詳解

doc ava 常見 每一個 document () 學習 知識 對象 js中的this指向十分重要,了解js中this指向是每一個學習js的人必學的知識點,今天沒事,正好總結了js中this的常見用法,喜歡的可以看看: 1、全局作用域或者普通函數中this指向全局對象wi

JavaScript this指向

UNC lar -c when ack regular poi ole die this 一方面便利了讓大家在JS開發當, 但是另一方面讓開發者頭痛的是不清楚this 指代什麽. 指向全局Window: <script> console.log(th

JavaScriptthis指標指向的徹底理解

現在我們就來總結一下js中this的指向。首先需要了解一下幾個概念: 1、全域性變數預設掛載在window物件下 2、一般情況下this指向它的呼叫者 3、es6的箭頭函式中,this指向建立者,並非呼叫者 4、通過call、apply、bind可以改改變this的指向 在非箭頭函式下, this

JavaScriptthis指向問題歸納總結

前言 js中this指向問題是個老生常談的問題了,下面這篇文章再來給大家介紹下,大家可以看看,更深入的瞭解瞭解,下面話不多說了,來一起看看詳細的介紹吧 this this:上下文,會根據執行環境變化而發生指向的改變. 1.單獨的this,指向的是window這個物件 alert(this); // this

JavaScriptthis關鍵字改變指向的三種方法(apply、call、bind)

首先,瞭解一下this關鍵字。this關鍵字就涉及到函式呼叫的內容。函式的幾種呼叫方式: 普通函式呼叫 作為方法來呼叫 作為建構函式來呼叫 使用apply/call方法來呼叫 Function.prototype.bind方法 ES6箭頭函式 但是不管

理解javascriptthis指向(簡單理解篇)

先列舉幾種常用的this指向: // 全域性下this=windowconsole.log(this==window);this.a = 1;console.log(window.a);// 物件屬性上函式的this指向的是物件objvar obj = {a:1,sayA

javascriptthis指向問題

this 指的是當前物件,如果在全域性範圍內使用this,則指代當前頁面window;如果在函式中使用this,則this指代什麼是根據當前函式是在什麼物件上呼叫。我們可以使用call和apply改變函式中this的具體指向。另外,在建構函式或者建構函式原型物件中this指向

徹底理解JavaScriptthis指向

在網上,大部分文章都會出現下面這段話:this的指向在函式定義的時候是確定不了的,只有在函式執行的時候才能確定this到底指向誰,實際上this最終指向的是那個呼叫他的物件這句話總是讓人有哦一種琢磨不透的感覺。為什麼要理解this?如果已經學過了面向物件,那麼就應該指導thi

javascriptthis詳解(史上最簡單易理解的講解,包你不再找錯this指向

判斷方法 this永遠指向一個物件,但普通函式與箭頭函式this指向不同。 普通函式: 普通函式的this是動態的,由函式是如何被呼叫的來決定。 ①是否使用了new以建構函式方式來呼叫函式,如果是則指向新建立的物件 ②是否使用(物件.屬性)的方式呼叫函式(如Obj.

十分鐘徹底理解javascriptthis指向,不懂請砸店

hub 改變 alert blog var rip def 徹底 文章 函數的this指向誰,和函數在哪裏被定義的,函數在哪裏被執行的沒有半毛錢關系,只遵守下面的規律: 在非嚴格模式中: 1、自執行函數裏面,this永遠指向window; <script

JavaScriptthis的用法

屬於 指向 cti 用法 func 生成 純粹 ava 構造函數 this的使用環境有以下幾種 1、純粹的函數調用 純粹的函數調用屬於函數的最常用的用法,屬於全局性調用。在全局函數中,this等於window。 2、作為對象方法的調用 當函數不是全局調用,而是作為某個對象

對於JavaScriptthis關鍵字的理解

決定 博客 rip script 答案 搜索 http 環境 return   這是我第二遍學this了,第一遍學的懵懵的。this指哪裏都是憑我一個男人的直覺然後控制臺輸出看看對不對。   剛查了書、博客、視頻。理解差不多了。畢竟菜雞me; 一、首先介紹下什麽是this

Javascript this的精要總結

實例 ref 今天 方法 自動 console 網上 這樣的 理解 對於javascript中this的指向問題,或許你和我一樣,總是很迷惑,今天通過學習了有些作者對這方面比較深刻的理解後,抄錄其中比較有用的精髓如下: 本文主要引用至:追夢子,如有需要可以導向去閱讀。 關鍵

淺析JavaScriptthis儲存

循環 變量名 當前 each ava var rip div 習慣 this是Javascript語言的一個關鍵字。它代表函數運行時,自動生成的一個內部對象,只能在函數內部使用。 在JavaScript中,this代表的是當前對象。 在寫原型鏈時,經常需要將this進行儲

JavaScript this 是如何工作的 ?

全局 val fst 如何使用 stephen 如何 系列 操作 link 先來看看這個題目: var x = 0; var foo = { x:1, bar:{ x:2, baz: function () { consol