[翻譯]JavaScript秘密花園 – hasOwnProperty,Functions,this

來源:互聯網
上載者:User
文章目錄
  • 結論(In conclusion)
  • 命名函數的賦值運算式(Named function expression)
  • 全域範圍內(The global scope)
  • 函數調用(Calling a function)
  • 方法調用(Calling a method)
  • 調用建構函式(Calling a constructor)
  • 常見誤解(Common pitfalls)
  • 方法的賦值運算式(Assigning methods)
  • JavaScript Garden - 原文
  • JavaScript Garden - 中文翻譯
hasOwnProperty

為了判斷一個對象是否包含自訂屬性而不是原型鏈上的屬性, 我們需要使用繼承自 Object.prototypehasOwnProperty 方法。

注意: 通過判斷一個屬性是否 undefined不夠的。 因為一個屬性可能確實存在,只不過它的值被設定為 undefined

hasOwnProperty 是JavaScript中唯一一個處理屬性但是不需要尋找原型鏈的方法。

// 修改Object.prototypeObject.prototype.bar = 1; var foo = {goo: undefined};foo.bar; // 1'bar' in foo; // truefoo.hasOwnProperty('bar'); // falsefoo.hasOwnProperty('goo'); // true

只有 hasOwnProperty 可以給出正確和期望的結果,這在遍曆對象的屬性時會很有用。 沒有其它方法可以用來排除原型鏈上的屬性,而不是定義在對象自身上的屬性。

hasOwnProperty 作為屬性( hasOwnProperty as a property)

JavaScript 不會保護 hasOwnProperty 被非法佔用,因此如果一個對象碰巧存在這個屬性, 就需要使用外部hasOwnProperty 函數來擷取正確的結果。

var foo = {    hasOwnProperty: function() {        return false;    },    bar: 'Here be dragons'};foo.hasOwnProperty('bar'); // 總是返回 false// 使用其它對象的 hasOwnProperty,並將其上下為設定為foo{}.hasOwnProperty.call(foo, 'bar'); // true
結論(In conclusion)

當檢查對象上某個屬性是否存在時,hasOwnProperty唯一可用的方法。 同時在使用 for in loop 遍曆對象時,推薦總是使用 hasOwnProperty 方法, 這將會避免原型對象擴充帶來的幹擾。

函數(Functions)

函數是JavaScript中的一等對象,這意味著可以把函數像其它值一樣傳遞。 一個常見的用法是把匿名函數作為回呼函數傳遞對非同步函數中。

函式宣告(The function declaration)
function foo() {}

上面的方法會在執行前被 解析(hoisted),因此它存在於當前內容相關的任意一個地方, 即使在函數定義體的上面被調用也是對的。

foo(); // 正常運行,因為foo在代碼運行前已經被建立function foo() {}
函數賦值運算式(The function expression)
var foo = function() {};

這個例子把一個匿名的函數賦值給變數 foo

foo; // 'undefined'foo(); // 出錯:TypeErrorvar foo = function() {};

由於 var 定義了一個聲明語句,對變數 foo 的解析是在代碼運行之前,因此 foo 變數在代碼運行時已經被定義過了。

但是由於指派陳述式只在運行時執行,因此在相應代碼執行之前, foo 的值預設為 undefined。

命名函數的賦值運算式(Named function expression)

另外一個特殊的情況是將命名函數賦值給一個變數。

var foo = function bar() {    bar(); // 正常運行}bar(); // 出錯:ReferenceError

bar 函式宣告外是不可見的,這是因為我們已經把函數賦值給了 foo; 然而在 bar 內部依然可見。這是由於 JavaScript 的 命名處理 所致, 函數名在函數內總是可見的。

this 的工作原理(How this works)

JavaScript 有一套完全不同於其它語言的對 this 的處理機制。 在種不同的情況下 ,this 指向的各不相同。

全域範圍內(The global scope)
this;

當在全部範圍內使用 this,它將會指向全域對象。 (譯者註:瀏覽器中啟動並執行JavaScript指令碼,這個全域對象是 window)

函數調用(Calling a function)
foo();

這裡 this 也會指向全域對象。

ES5 注意: 在strict 模式下(strict mode),不存在全域變數。 這種情況下 this 將會是 undefined。 (譯者註:ES5指的是ECMAScript 5,是2009-12發布的最新的 JavaScript 版本。)

方法調用(Calling a method)
test.foo();

這個例子中,this 指向 test 對象。

調用建構函式(Calling a constructor)
new foo();

如果函數傾向於和 new 關鍵詞一塊使用,則我們稱這個函數是 建構函式。 在函數內部,this 指向新建立的對象。

顯式的設定 this(Explicit setting of this
function foo(a, b, c) {}var bar = {};foo.apply(bar, [1, 2, 3]); // 數組將會被擴充,如下所示foo.call(bar, 1, 2, 3); // 傳遞到foo的參數是:a = 1, b = 2, c = 3

當使用 Function.prototype 上的 call 或者 apply 方法時,函數內的 this 將會被 顯式設定為函數調用的第一個參數。

因此函數調用的規則在上例中已經不適用了,在foo 函數內 this 被設定成了 bar

注意: 在對象的字面聲明文法中,this 不能用來指向對象本身。 因此 var obj = {me: this} 中的 me 不會指向 obj,因為 this 只可能出現在上述的五種情況中。 (譯者註:這個例子中,如果是在瀏覽器中運行,obj.me等於window對象。)

常見誤解(Common pitfalls)

儘管大部分的情況都說的過去,不過第一個規則(譯者註:這裡指的應該是第二個規則,也就是直接調用函數時,this 指向全域對象) 被認為是JavaScript語言另一個錯誤設計的地方,因為它從來就沒有實際的用途。

Foo.method = function() {    function test() {        // this 將會被設定為全域對象(譯者註:瀏覽器環境中也就是 window 對象)    }    test();}

一個常見的誤解是 test 中的 this 將會指向 Foo 對象,實際上不是這樣子的。

為了在 test 中擷取對 Foo 對象的引用,我們需要在 method 函數內部建立一個局部變數指向 Foo 對象。

Foo.method = function() {    var that = this;    function test() {        // 使用 that 來指向 Foo 對象    }    test();}

that 只是我們隨意起的名字,不過這個名字被廣泛的用來指向外部的 this 對象。 在 closures 一節,我們可以看到 that 可以作為參數傳遞。

方法的賦值運算式(Assigning methods)

另一個看起來奇怪的地方是函數別名,也就是將一個方法賦值給一個變數。

var test = someObject.methodTest;test();

上例中,test 就像一個普通的函數被調用;因此,函數內的 this 將不再被指向到 someObject 對象。

雖然 this 的晚綁定特性似乎並不友好,但是這確實基於原型繼承賴以生存的土壤。

function Foo() {}Foo.prototype.method = function() {};function Bar() {}Bar.prototype = Foo.prototype;new Bar().method();

method 被調用時,this 將會指向 Bar 的執行個體對象。

本中文翻譯由三上石上原創,部落格園首發,轉載請註明出處。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.