成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

從Vue源碼學(xué)習(xí)JavaScript之this instanceof Vue

付永剛 / 3167人閱讀

摘要:函數(shù)的調(diào)用有以下幾種方式作為對(duì)象方法調(diào)用,作為函數(shù)調(diào)用,作為構(gòu)造函數(shù)調(diào)用,和使用或調(diào)用。并且規(guī)范中說(shuō)明,只有對(duì)象實(shí)現(xiàn)了方法。使用了回到上面作為構(gòu)造函數(shù)調(diào)用第一步創(chuàng)建一個(gè)空的對(duì)象,。第二步鏈接該對(duì)象即設(shè)置該對(duì)象的構(gòu)造函數(shù)到另一個(gè)對(duì)象,即。

在src/core/instance/index.js中

if (process.env.NODE_ENV !== "production" &&
!(this instanceof Vue)
) {
    warn("Vue is a constructor and should be called with the `new` keyword")
 }

這里通過(guò)this instanceof Vue來(lái)判斷有沒(méi)有用new關(guān)鍵詞調(diào)用,為什么可以這么判斷?我們分別了解一下this和instanceof的用法

this

在 JavaScript 中,this 是動(dòng)態(tài)綁定,或稱(chēng)為運(yùn)行期綁定的,它可以是全局對(duì)象、當(dāng)前對(duì)象或者任意對(duì)象,這取決于函數(shù)的調(diào)用方式。函數(shù)的調(diào)用有以下幾種方式:作為對(duì)象方法調(diào)用,作為函數(shù)調(diào)用,作為構(gòu)造函數(shù)調(diào)用,和使用 apply 或 call 調(diào)用。

1、作為對(duì)象方法調(diào)用

var point = { 
    x : 0, 
    y : 0, 
    moveTo : function(x, y) { 
        this.x = this.x + x; 
        this.y = this.y + y; 
    } 
}; 

point.moveTo(1, 1)//this 綁定到當(dāng)前對(duì)象,即 point 對(duì)象

2、作為函數(shù)調(diào)用

function makeNoSense(y) { 
    this.x = y; 
} 
 
makeNoSense(5); 
x;// 調(diào)用函數(shù)的對(duì)象是window,所以x 已經(jīng)成為一個(gè)值為 5 的全局變量

下面,我們看另一種情況

var point = { 
    x : 0, 
    y : 0, 
    moveTo : function(x, y) { 
        // 內(nèi)部函數(shù)
        var moveX = function(x) { 
        this.x = x;//this 綁定到了哪里?
       }; 
       // 內(nèi)部函數(shù)
       var moveY = function(y) { 
       this.y = y;//this 綁定到了哪里?
       }; 
     
       moveX(x); 
       moveY(y); 
       } 
}; 
point.moveTo(1, 1); 
point.x; //==>0 
point.y; //==>0 
x; //==>1 
y; //==>1

this除了指向它的直接調(diào)用者外,還有一種情況就是如果沒(méi)有明確的調(diào)用對(duì)象的時(shí)候,將對(duì)函數(shù)的this使用默認(rèn)綁定:綁定到全局的window對(duì)象。

3、作為構(gòu)造函數(shù)調(diào)用

function Point(x, y){ 
   this.x = x; 
   this.y = y; 
}
var test = new Point(1, 2)

我們需要理解的是,new運(yùn)算符做了什么:

第一步: 創(chuàng)建一個(gè)空的對(duì)象,{}。
第二步: 鏈接該對(duì)象(即設(shè)置該對(duì)象的構(gòu)造函數(shù))到另一個(gè)對(duì)象,即o.\__proto__ == Point.prototype。
第三步: 將步驟1新創(chuàng)建的對(duì)象作為this的上下文
第四步: 如果該函數(shù)沒(méi)有返回對(duì)象,則返回this

4、使用 apply 或 call 調(diào)用

apply和call可以切換函數(shù)執(zhí)行的上下文環(huán)境(context)

function add(x, y) {
    console.log(x + y)
}

function del(x, y) {
    console.log(x - y)
}

add.call(del, 3, 1) // 4
instanceof

1、通常來(lái)講,使用 instanceof 就是判斷一個(gè)實(shí)例是否屬于某種類(lèi)型,比如:

// 判斷 foo 是否是 Foo 類(lèi)的實(shí)例
function Foo(){} 
var foo = new Foo(); 
console.log(foo instanceof Foo)//true

2、另外,更重要的一點(diǎn)是 instanceof 可以在繼承關(guān)系中用來(lái)判斷一個(gè)實(shí)例是否屬于它的父類(lèi)型。例如:

// 判斷 foo 是否是 Foo 類(lèi)的實(shí)例 , 并且是否是其父類(lèi)型的實(shí)例
function Aoo(){} 
function Foo(){} 
Foo.prototype = new Aoo();//JavaScript 原型繼承
 
var foo = new Foo(); 
console.log(foo instanceof Foo)//true 
console.log(foo instanceof Aoo)//true

上面的代碼中是判斷了一層繼承關(guān)系中的父類(lèi),在多層繼承關(guān)系中,instanceof 運(yùn)算符同樣適用。

3、ECMAScript中instanceof的定義

11.8.6 The instanceof operator 
The production RelationalExpression:
 RelationalExpression instanceof ShiftExpression is evaluated as follows: 
 1. Evaluate RelationalExpression. 
 2. Call GetValue(Result(1)).// 調(diào)用 GetValue 方法得到 Result(1) 的值,設(shè)為 Result(2) 
 3. Evaluate ShiftExpression. 
 4. Call GetValue(Result(3)).// 同理,這里設(shè)為 Result(4) 
 5. If Result(4) is not an object, throw a TypeError exception.// 如果 Result(4) 不是 object,
                                                                //拋出異常
 /* 如果 Result(4) 沒(méi)有 [[HasInstance]] 方法,拋出異常。規(guī)范中的所有 [[...]] 方法或者屬性都是內(nèi)部的,
在 JavaScript 中不能直接使用。并且規(guī)范中說(shuō)明,只有 Function 對(duì)象實(shí)現(xiàn)了 [[HasInstance]] 方法。
所以這里可以簡(jiǎn)單的理解為:如果 Result(4) 不是 Function 對(duì)象,拋出異常 */ 
 6. If Result(4) does not have a [[HasInstance]] method, 
   throw a TypeError exception. 
 // 相當(dāng)于這樣調(diào)用:Result(4).[[HasInstance]](Result(2)) 
 7. Call the [[HasInstance]] method of Result(4) with parameter Result(2). 
 8. Return Result(7). 
 // 相關(guān)的 HasInstance 方法定義
 15.3.5.3 [[HasInstance]] (V) 
 Assume F is a Function object.// 這里 F 就是上面的 Result(4),V 是 Result(2) 
 When the [[HasInstance]] method of F is called with value V, 
     the following steps are taken: 
 1. If V is not an object, return false.// 如果 V 不是 object,直接返回 false 
 2. Call the [[Get]] method of F with property name "prototype".// 用 [[Get]] 方法取 
                                                                // F 的 prototype 屬性
 3. Let O be Result(2).//O = F.[[Get]]("prototype") 
 4. If O is not an object, throw a TypeError exception. 
 5. Let V be the value of the [[Prototype]] property of V.//V = V.[[Prototype]] 
 6. If V is null, return false. 
 // 這里是關(guān)鍵,如果 O 和 V 引用的是同一個(gè)對(duì)象,則返回 true;否則,到 Step 8 返回 Step 5 繼續(xù)循環(huán)
 7. If O and V refer to the same object or if they refer to objects 
   joined to each other (section 13.1.2), return true. 
 8. Go to step 5.
 

翻譯成 JavaScript 代碼如下所示:

function instance_of(L, R) {//L 表示左表達(dá)式,R 表示右表達(dá)式
 var O = R.prototype;// 取 R 的顯示原型
 L = L.__proto__;// 取 L 的隱式原型
 while (true) { 
   if (L === null) 
     return false; 
   if (O === L)// 這里重點(diǎn):當(dāng) O 嚴(yán)格等于 L 時(shí),返回 true 
     return true; 
   L = L.__proto__; 
 } 
}

從代碼中我們可以看到,instanceof是比較左側(cè)的__proto__(隱式原型)和右側(cè)的prototype(顯示原型)是否相等,如果不相等,取左側(cè)__proto__的__proto__,依次循環(huán)比較,直到取到Object.prototype.__proto__即null為止。有關(guān)__proto__和prototype請(qǐng)查看我這篇博客

回到主題,this instanceof Vue我們可以這么分解:this.__proto__和Vue.prototype

沒(méi)有使用new

this指向window,結(jié)果為false。

使用了new

回到上面作為構(gòu)造函數(shù)調(diào)用:

    第一步: 創(chuàng)建一個(gè)空的對(duì)象,vat o = {}。
    第二步: 鏈接該對(duì)象(即設(shè)置該對(duì)象的構(gòu)造函數(shù))到另一個(gè)對(duì)象,即o.\__proto__ == Vue.prototype。
    第三步: 將步驟1新創(chuàng)建的對(duì)象作為this的上下文
    第四步: 如果該函數(shù)沒(méi)有返回對(duì)象,則返回this
    

所以,結(jié)果可以看做這樣:

o.\__proto__ == this.\__proto__  == Vue.prototype

所以如果用new操作符的話(huà),this instanceof Vue結(jié)果為true。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/103962.html

相關(guān)文章

  • vue源碼學(xué)習(xí)(一)——入口開(kāi)始

    摘要:學(xué)習(xí)源碼時(shí),我們首先需要看的是文件,該文件里配置了的依賴(lài)以及開(kāi)發(fā)環(huán)境和生產(chǎn)環(huán)境的編譯的啟動(dòng)腳本等其他信息。一個(gè)是完整版,一個(gè)是運(yùn)行時(shí)。運(yùn)行時(shí)用來(lái)創(chuàng)建實(shí)例渲染并處理虛擬等的代碼。基本上就是除去編譯器的其它一切。 學(xué)習(xí)vue源碼時(shí),我們首先需要看的是package.json文件,該文件里配置了vue的依賴(lài)以及開(kāi)發(fā)環(huán)境和生產(chǎn)環(huán)境的編譯的啟動(dòng)腳本等其他信息。首先我們需要關(guān)注的是script。我...

    ybak 評(píng)論0 收藏0
  • 簡(jiǎn)述vue-router實(shí)現(xiàn)原理

    摘要:源碼解讀閱讀請(qǐng)關(guān)注下代碼注釋打個(gè)廣告哪位大佬教我下怎么排版啊,不會(huì)弄菜單二級(jí)導(dǎo)航撲通是什么首先,你會(huì)從源碼里面引入,然后再傳入?yún)?shù)實(shí)例化一個(gè)路由對(duì)象源碼基礎(chǔ)類(lèi)源碼不選擇模式會(huì)默認(rèn)使用模式非瀏覽器環(huán)境默認(rèn)環(huán)境根據(jù)參數(shù)選擇三種模式的一種根據(jù)版 router源碼解讀 閱讀請(qǐng)關(guān)注下代碼注釋 打個(gè)廣告:哪位大佬教我下sf怎么排版啊,不會(huì)弄菜單二級(jí)導(dǎo)航(撲通.gif) showImg(https:...

    Cristalven 評(píng)論0 收藏0
  • 簡(jiǎn)述vue-router實(shí)現(xiàn)原理

    摘要:源碼解讀閱讀請(qǐng)關(guān)注下代碼注釋打個(gè)廣告哪位大佬教我下怎么排版啊,不會(huì)弄菜單二級(jí)導(dǎo)航撲通是什么首先,你會(huì)從源碼里面引入,然后再傳入?yún)?shù)實(shí)例化一個(gè)路由對(duì)象源碼基礎(chǔ)類(lèi)源碼不選擇模式會(huì)默認(rèn)使用模式非瀏覽器環(huán)境默認(rèn)環(huán)境根據(jù)參數(shù)選擇三種模式的一種根據(jù)版 router源碼解讀 閱讀請(qǐng)關(guān)注下代碼注釋 打個(gè)廣告:哪位大佬教我下sf怎么排版啊,不會(huì)弄菜單二級(jí)導(dǎo)航(撲通.gif) showImg(https:...

    Ajian 評(píng)論0 收藏0
  • vue 源碼學(xué)習(xí)(二) 實(shí)例初始化和掛載過(guò)程

    摘要:最后判斷有無(wú)根節(jié)點(diǎn),無(wú)則表示首次掛載,添加鉤子函數(shù),返回總結(jié)實(shí)例初始化掛載方法屬性初始化掛載過(guò)程在版本,生成函數(shù)對(duì)作處理,執(zhí)行中定義了通過(guò)實(shí)例化的回調(diào)執(zhí)行執(zhí)行,即調(diào)用了真實(shí)渲染成對(duì)象。 vue 入口 從vue的構(gòu)建過(guò)程可以知道,web環(huán)境下,入口文件在 src/platforms/web/entry-runtime-with-compiler.js(以Runtime + Compile...

    時(shí)飛 評(píng)論0 收藏0

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

0條評(píng)論

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