JS 特性彙總

1 預解析-Hoisting函數

■變量提高oop

變量提高,很簡單,就是把變量提高提到函數的top的地方。我麼須要說明的是,變量提高 只是提高變量的聲明,並不會把賦值也提高上來this

一般,各種文章和JavaScript相關的書籍都聲稱:「不論是使用var關鍵字(在全局上下文)仍是不使用var關鍵字(在任何地方),均可以聲明一個變量」。請記住,這是錯誤的概念:spa

任什麼時候候,變量只能經過使用var關鍵字才能聲明。prototype

上面的賦值語句:code

a = 10;

這僅僅是給全局對象建立了一個新屬性(但它不是變量)。「不是變量」並非說它不能被改變,而是指它不符合ECMAScript規範中的變量概念,因此它「不是變量」(它之因此能成爲全局對象的屬性,徹底是由於VO(globalContext) === global,你們還記得這個吧?)。orm

■函數提高 對象

函數類型 提高能否 函數名有無 局部做用域使用與否
函數申明方式
YES 必須有 YES
函數表達式方式
NO 無關緊要 YES
函數構造器方式
NO NO NO

   ◆函數申明方式(函數調用在函數申明以前,依然能夠調用ip

function myTest(){ 
    foo(); 
    function foo(){ 
        alert("我來自 foo"); 
    } 
} 
myTest();

   ◆函數表達式方式(函數調用在函數表達式以前,不能調用.調用後⇒×TypeError foo is not a function原型鏈

function myTest(){ 
    foo(); 
    var foo =function foo(){ 
        alert("我來自 foo"); 
    } 
} 
myTest();

   ◆函數構造器方式(不使用局部做用域

var y = "global"; 
function constructFunction() { 
var y = "local"; 
//Function()構造函數 
//不使用局部做用域
return new Function("return y;"); 
} 

function constFunction() { 
var y = "local"; 
//函數直接量 
var f = function () { 
//使用局部做用域 
return y;
}; 
return f; 
} 
//顯示 global,由於Function()構造函數返回的函數並不使用局部做用域 
alert(constructFunction()()); 
//顯示 lobal,由於函數直接量返回的函數並使用局部做用域 
alert(constFunction()());

■函數申明和變量申明的關係和影響

 function a(x) {
     x * 2;
  }
 var a;
 alert(a);

遇到同名的函數聲明,VO不會從新定義,因此這時候全局的VO應該是以下這樣的:

VO(global) = {
    a: 引用了函數聲明「a」
}

而執行a的時候,相應地就彈出了函數a的內容了。


hasOwnProperty函數

hasOwnProperty是Object.prototype的一個方法,它但是個好東西,他能判斷一個對象是否包含自定義屬性而不是原型鏈上的屬性,由於hasOwnProperty 是 JavaScript 中惟一一個處理屬性可是不查找原型鏈的函數。

// 修改Object.prototype
Object.prototype.bar = 1; 
var foo = {goo: undefined};

foo.bar; // 1
'bar' in foo; // true

foo.hasOwnProperty('bar'); // false
foo.hasOwnProperty('goo'); // true

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

但有個噁心的地方是:JavaScript 不會保護 hasOwnProperty 被非法佔用,所以若是一個對象碰巧存在這個屬性,就須要使用外部的 hasOwnProperty 函數來獲取正確的結果

var foo = {
    hasOwnProperty: function() {
        return false;
    },
    bar: 'Here be dragons'
};
foo.hasOwnProperty('bar'); // 老是返回 false

// 使用{}對象的 hasOwnProperty,並將其上下爲設置爲foo
{}.hasOwnProperty.call(foo, 'bar'); // true

當檢查對象上某個屬性是否存在時,hasOwnProperty 是惟一可用的方法。同時在使用 for in loop 遍歷對象時,推薦老是使用 hasOwnProperty 方法,這將會避免原型對象擴展帶來的干擾,咱們來看一下例子:

// 修改 Object.prototype
Object.prototype.bar = 1;

var foo = {moo: 2};
for(var i in foo) {
    console.log(i); // 輸出兩個屬性:bar 和 moo
}

咱們沒辦法改變for in語句的行爲,因此想過濾結果就只能使用hasOwnProperty 方法,代碼以下:

// foo 變量是上例中的
for(var i in foo) {
    if (foo.hasOwnProperty(i)) {
        console.log(i);
    }
}

這個版本的代碼是惟一正確的寫法。因爲咱們使用了 hasOwnProperty,因此此次只輸出 moo。若是不使用 hasOwnProperty,則這段代碼在原生對象原型(好比 Object.prototype)被擴展時可能會出錯。

總結:推薦使用 hasOwnProperty,不要對代碼運行的環境作任何假設,不要假設原生對象是否已經被擴展了。

3 this

3.1在全局代碼中,this始終是全局對象自己,這樣就有可能間接的引用到它了。

3.2在一般的函數調用中,this是由激活上下文代碼的調用者來提供的,即調用函數的父上下文(parent context )。this取決於調用函數的方式。

   如下是經典案例↓

foo() {
  alert(.bar);
}

x = {bar: 10};
y = {bar: 20};

x.test = foo;
y.test = foo;
 
x.test(); y.test();
相關文章
相關標籤/搜索