JavaScript 高級特性

1. 原型Prototype

1.1 構造函數

  所謂"構造函數",其實就是一個普通函數,可是內部使用了this變量。對構造函數使用new運算符,就能生成實例,而且this變量會綁定在實例對象上。  javascript

 

function Cat(name, color) {
    this.name = name;
    this.color = color;
}

var cat1 = new Cat("大毛", "黃色");
var cat2 = new Cat("二毛", "黑色");
alert(cat1.name); // 大毛
alert(cat1.color); // 黃色

//這時cat1和cat2會自動含有一個constructor屬性,指向它們的構造函數。
cat1.constructor == Cat; //true
cat2.constructor == Cat; //true

function Cat(name, color) {
    this.name = name;
    this.color = color;
    this.type = "貓科動物";
    this.eat = function () { alert("吃老鼠"); };
}

cat1.type; // 貓科動物
cat1.eat(); // 吃老鼠
//每個實例對象,每一次生成重複內容內存,可是內存地址不同
cat1.eat == cat2.eat; //false

 

1.2 實例.constructor

  每一個構造函數生成實例的時候 會自帶一個constructor屬性 指向該構造函數。對於普通對象生成實例時,constructor指向其類型的構造函數。html

  結論1: 實例.constructor == 構造函數java

function Cat(name) {
    this.name = name;
}
var cat1 = new Cat("大毛");
cat1.constructor == Cat; //true

var str1 = "123";
str1.constructor == String;//true

 

1.3 實例.prototype

  構造函數都有一個prototype屬性,指向另外一個對象。這個對象的全部屬性和方法,都會被構造函數的實例繼承瀏覽器

  對該構造函數的實例,繼承的prototype對象都指向同一個。    閉包

  結論2: 實例1.prototype.func == 實例2.prototype.func函數

function Cat(name, color) {
    this.name = name;
    this.color = color;
}
Cat.prototype.type = "貓科動物";
Cat.prototype.eat = function () { alert("吃老鼠") };

cat1.eat == cat2.eat;//true
// hasOwnProperty判斷是本身自己的屬性仍是繼承的
cat1.hasOwnProperty("name"); //true
cat1.hasOwnProperty("type"); //false

 

1.4 實例.__proto__ 

  Javascript建立對象時(普通對象和函數對象),都會內置一個__proto__屬性,指向 實例的建立函數(實例.constructor).prototypethis

  結論3: 實例.__proto__ === 構造函數.prototype spa

  同理: 構造函數.prototype.__proto__ === Object.prototype prototype

 

2. 做用域Scope

2.1 全局變量

  全局聲明的變量,瀏覽器環境實際上聲明在頂層變量"window"下。指針

  函數內部聲明變量時,未使用var關鍵字,會聲明爲全局變量。  

function f1() {
    n = 999;
}
f1();//調用函數時,n被註冊到全局
alert(n); // 999
alert(window.n); // 999

  

2.2 局部變量

  只能在局部使用並可見的變量,如函數內部聲明的變量  

function f2() {
    var n = 999;
    alert(n);//999
}
alert(n);//報錯

2.3 鏈式做用域

  父對象的全部變量,對子對象都是可見的,反之則不成立

//子對象會一級一級地向上尋找全部父對象的變量
function f1() {
    var n = 999;
    function f2() {
        //n對f2可見
        alert(n); // 999
    }
}

 

3. 閉包Closure

   什麼是閉包; 定義在一個函數內部的函數 (閉包就是可以讀取其餘函數內部變量的函數)

//下面的f2就是一個閉包
function f1() {
    var n = 999;
    function f2() {
        alert(n);
    }
    return f2;
}
var result = f1();
result(); // 999
//注意result後跟的(),這對括號纔是實際調用

用途:

  • 讀取函數內部的變量
  • 讓函數內部變量的值始終保持在內存中

閉包執行時的this指針指向問題

var name = "The Window";
var object = {
    name: "My Object",
    getNameFunc: function () {
        return function () {
            return this.name;
        };
    }
};

alert(object.getNameFunc()());//The Window
//上面這句解開後等於 
alert(function () { return this.name; }()); //此時this指針指向當前域下的name="The Window"
var name = "The Window";
var object = {
    name: "My Object",
  getNameFunc: function () {
   var that = this;
      return function () {
          return that.name;
     };
  }
};

alert(object.getNameFunc()());//My Object //分解以下
alert(function () { return that.name; }());//that是對object內部this變量的引用, object內部this指向實例自己
alert(function () { return object.name; }());//最終如此

 

 

refers:

http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html

http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html

相關文章
相關標籤/搜索