日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Javascript中的对象查找【转】

發(fā)布時間:2024/10/8 java 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Javascript中的对象查找【转】 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
編輯點評:本文作者為大家介紹Javascript中的對象查找一些問題,希望有所幫助。

  近期群里常有人提一些簡單的問題,比如發(fā)一段代碼亂七八糟的代碼,然后說里面某個變量是什么,比如這里就有個很好的例子:

function fn(arg) {
alert(
this.arg);
alert(
this);
}
fn(
123);
var o = { fn: fn };
o.fn(
123);

  然后就可能有這樣的問題:

為什么this.arg是undefined?為什么2次調(diào)用fn的this是不一樣的?

  為此,我覺得自己作為一個雖然不成熟的前端,對于一些自己力所能及的事情,還是應該傳道授業(yè)解惑的。所以,這篇文章,計劃從非常膚淺的層面上,來解釋一下javascript中的對象查找是如何進行的。

  注意,本篇文章只是從表象上來介紹對象查找這一行為的過程,文章中的觀點并不全正確,甚至存在著一些謬誤,但是這也是為了讓初學者更好地理解對象查找這一過程。相信如果說得太過抽象、深入,反而會引起一些負面效果。如果有一天,你再回過來,發(fā)現(xiàn)這個文章說得并不那么正確,那么恭喜你,那個時候的你已經(jīng)可以找到正確前進的道路,這篇中的錯誤也不會再對你有任何影響。

  對象的分類

  所謂對象查找,即在一段可執(zhí)行代碼的作用域內(nèi),找到一個當前需要的對象。在javascript中,需要進行查找的對象大致可以分為3種類型:

  • 變量查找,如foo++;,這里就會去查找一個叫作foo的變量。
  • 屬性查找,如foo.bar++;,這里會去查找foo這個變量下的一個叫作bar的屬性。
  • this查找,即針對this關(guān)鍵字的處理。

  區(qū)分這3種類型的對象查找是首先要完成的任務(wù),你可以基于以下原則進行判斷:

  • 變量僅由變量名組成,即單獨的foo、bar等。
  • 屬性永遠由2種形式去訪問,即foo.bar和foo['bar'],因此看到有“.”或“[]”即可當成是屬性查找。
  • this就不用說了,好好的關(guān)鍵字。

  看一下這段代碼:

var foo = this;
foo.bar();

  這2行的代碼就體現(xiàn)了3種對象查找,分別為:

  • 查找this對象,并賦值給foo變量。
  • 查看foo變量。
  • 查找foo變量下的bar屬性,并將之作為一個函數(shù)進行調(diào)用。
  •   變量的查找

      當確定一個對象的查找為變量查找后,可以按照變量查找的規(guī)則來查看。

      變量查找,即在作用域鏈上進行查找,作用域鏈是javascript非常著名的2條鏈之一,以下代碼體現(xiàn)一個標準的作用域鏈:

    var foo = 1;
    function a() {
    var bar = 2;
    function b() {
    foo
    = 3;
    function c() {
    alert(foo
    + ',' + bar); // 注意這一行
    }
    c();
    }
    b();
    }
    a();

      在c函數(shù)中,一共進行了2個變量的查找,分別為foo和bar。

      變量的查找可以簡單地遵守“從下向上”的原則,即:

  • 在函數(shù)c的范圍內(nèi)查找foo和bar,顯然在c里面并沒有foo和bar的聲明,查找失敗。
  • 在包含c的函數(shù),即函數(shù)b的范圍內(nèi)查找foo和bar,可以看到b里面只有對foo的賦值,并沒有聲明,查找失敗。
  • 在包括b的函數(shù),即函數(shù)a的范圍內(nèi)查找foo和bar,可以找到bar的聲明,因此確定bar為2。
  • 由于a不被任何函數(shù)包含,那么就在全局作用域內(nèi)查找foo,發(fā)現(xiàn)有foo的聲明,因此確定foo的值為1。但是由于在函數(shù)b中,對這個foo有賦值,所以foo的值被修改為3。
  • 完確定foo的值為3,bar的值為2,因此輸出"3,2"。
  •   總結(jié)一下,變量的查找是延著作用域鏈進行的,作用域鏈可以簡單地看成函數(shù)間的包含關(guān)系,被包含的函數(shù)中不存在某個變量時,在包含他的函數(shù)中查找,直到全局作用域。

      屬性的查找

      當確定一個對象的查找為屬性查找后,可以按照屬性查找的規(guī)則來查看。

      屬性查找,即在原型鏈上進行查找,原型鏈是javascript雙鏈的另一條,以下可以表示出一個原型鏈:

    var a = function() {};
    var b = function() {};
    var c = function() {};
    b.prototype
    = new a();
    c.prototype
    = new b();
    a.prototype.foo
    = 1;
    b.prototype.bar
    = 2;
    c.prototype.foo
    = 3;
    var o = new c();
    alert(o.foo
    + ',' + o.bar); // 這一行進行查找

      屬性查找是一個不斷尋找prototype的過程,即:

  • 查找c.prototype中,有沒有顯示定義foo和和bar,發(fā)現(xiàn)定義了foo,其值為3。
  • 發(fā)現(xiàn)c.prototype就是new b()得到的對象,那么查找b.prototype中,有沒有顯示定義bar,發(fā)現(xiàn)定義了,其值為2。
  • 因此確定foo的值為3,bar的值為2,輸出"3,2"。
  •   總結(jié)一下,屬性查找是延著原型鏈進行的,原型鏈的具體知識這里不作詳細解釋,可以另找文章進行參考。所有的對象,其原型鏈最終會是Object.prototype。

      this的查找

      this的查找是很多人迷茫的一點,也似乎有很多人抱有this不穩(wěn)定這樣的看法,實在令人無語。this的查找可以說是3種對象查找中最為簡單的,因為其實this對象的確定根本沒有一個“查找”的過程。

      首先,this對象只會在一個函數(shù)中需要確定,如果是在全局域下,this永遠為Global對象,在瀏覽器中通常就是window對象。而在javascript中,函數(shù)的調(diào)用一共有4種方式:

    Function Invocation Pattern

    諸如`foo()`的調(diào)用形式被稱為Function Invocation Pattern,是函數(shù)最直接的使用形式,注意這里的foo是作為單獨的變量出現(xiàn),而不是屬性。

    在這種模式下,foo函數(shù)體中的this永遠為Global對象,在瀏覽器中就是window對象。

    Method Invocation Pattern

    諸如`foo.bar()`的調(diào)用形式被稱為Method Invocation Pattern,注意其特點是被調(diào)用的函數(shù)作為一個對象的屬性出現(xiàn),必然會有“.”或者“[]”這樣的關(guān)鍵符號。

    在這種模式下,bar函數(shù)體中的this永遠為“.”或“[”前的那個對象,如上例中就一定是foo對象。

    Constructor Pattern

    `new foo()`這種形式的調(diào)用被稱為Constructor Pattern,其關(guān)鍵字`new`就很能說明問題,非常容易識別。

    在這種模式下,foo函數(shù)內(nèi)部的this永遠是new foo()返回的對象。

    Apply Pattern

    `foo.call(thisObject)`和`foo.apply(thisObject)`的形式被稱為Apply Pattern,使用了內(nèi)置的`call`和`apply`函數(shù)。

    在這種模式下,`call`和`apply`的第一個參數(shù)就是foo函數(shù)體內(nèi)的this,如果thisObject是`null`或`undefined`,那么會變成Global對象。

      應用以上4種方式,確定一個函數(shù)是使用什么樣的Pattern進行調(diào)用的,就能很容易確定this是什么。

      另外,this是永遠不會延作用域鏈或原型鏈出現(xiàn)一個“查找”的過程的,只會在函數(shù)調(diào)用時就完全確認。

      總結(jié)

      對于一個對象的查找:

  • 確定是變量查找、屬性查找還是this查找。
  • 如果是變量查找,則延作用域鏈找,找不到就是ReferenceError。
  • 如果是屬性查找,就延原型鏈找,找歪以就是undefined。
  • 如果是this查找,去找調(diào)用函數(shù)的代碼,根據(jù)調(diào)用的形式來確定this是什么。
  • 注意把一次查找過程拆分開來,比如this.foo.bar.yahoo(),可以拆分成這樣的代碼,就能更清楚了:

    var o = this; // this查找
    var foo = o.this; // 屬性查找
    var bar = foo.bar; // 屬性查找
    bar.yahoo(); // 屬性查找,加Method Invocation Pattern
  •   最后,如果有一天你可以了解這些東西,這篇文章對你用戶也就不大了:

    • 為什么延作用域查找不到會有ReferenceError。
    • 其實變量也是屬性,一個特殊對象的屬性。
    • this也許不是Global,也許會是undefined。

    轉(zhuǎn)載于:https://www.cnblogs.com/tangge/archive/2011/04/26/2029295.html

    總結(jié)

    以上是生活随笔為你收集整理的Javascript中的对象查找【转】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。