JavaScript高程第三版筆記-面向對象編程

以前有篇博客曾提到過一點js的面向對象編程:js面向對象編程.javascript

這裏就結合js高程詳細剖析一下javascript的面向對象編程.html

前序:vue

1⃣️Object.defineProperty()java

    var obj = {
      _name:'jack'
    };
    Object.defineProperty(obj,'name',{
      configurable:false,//表示可否經過delete刪除屬性從而從新定義屬性,默認值true
      value:'orange',//屬性的數據值,默認值undefined
      writable:false,//表示可否修改屬性的值,默認值爲true
      enumerable:false,//是否可枚舉,可否經過for-in循環返回屬性,默認值爲true
      get:function(){//getter
        return this._name;
      },
      set:function(newval){//setter
        this._name = newval;
      }
    })

vue2.x版本的雙向數據綁定就是基於該API和訂閱/發佈模式實現的;編程

若是同時定義多個屬性,可經過以下API:函數

Object.defineProperties(book, {
    _year: {
        value: 2004
    },
    edition: {
        value: 1
    },
    year: {
        get: function(){
            return this._year;
        },
        set: function(newValue){
            if (newValue > 2004) {
                this._year = newValue;
                this.edition += newValue - 2004;
            }
        }
} });

2⃣️讀取屬性的特性Object.getOwnPropertyDescriptor() this

var descriptor = Object.getOwnPropertyDescriptor(book, "_year");
alert(descriptor.value); //2004
alert(descriptor.configurable); //false

 

正文:spa

3⃣️建立對象prototype

3.1 工廠模式code

function createPerson(name, age, job){
        var o = new Object();
        o.name = name;
        o.age = age;
        o.job = job;
        o.sayName = function(){
            alert(this.name);
        };
        return o; 
}
var person1 = createPerson("Nicholas", 29, "Software Engineer"); var person2 = createPerson("Greg", 27, "Doctor");

工廠模式建立了n個互不關聯的對象,可是卻沒有解決對象識別的問題(即怎樣知道一個對象的類型) .

3.2 構造函數模式

function Person(name, age, job){
        this.name = name;
        this.age = age;
        this.job = job;
        this.sayName = function(){
            alert(this.name);
}; }
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");

由於函數也是一個對象,因此能夠經過該方式建立一個Person對象;

按照慣例,構造函數始終都應該以一個 大寫字母開頭,而非構造函數則應該以一個小寫字母開頭 ;

要建立 Person 的新實例,必須使用 new 操做符。以這種方式調用構造函數實際上會經歷如下 4 個步驟:

(1) 建立一個新對象;
(2) 將構造函數的做用域賦給新對象(所以 this 就指向了這個新對象);
(3) 執行構造函數中的代碼(爲這個新對象添加屬性);
(4) 返回新對象。

alert(person1.constructor == Person); //true
alert(person2.constructor == Person); //true
alert(person1 instanceof Object);  //true
alert(person1 instanceof Person);  //true
alert(person2 instanceof Object);  //true
alert(person2 instanceof Person);  //true

構造函數模式雖然好用,但也並不是沒有缺點。使用構造函數的主要問題,就是每一個方法都要在每一個實例上從新建立一遍,不能共享。雖然咱們能夠將該方法寫到全局做用域,而後在構造函數內部調用,可是這種作法顯然耦合度太高.

3.3 原型模式

能夠順便參照以前的博客:js繼承的實現.

function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
    alert(this.name);
};
var person1 = new Person();
person1.sayName();   //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName);  //true

能夠看到,原型屬性上的屬性值和屬性方法是被全部實例共享的.

3.3.1實例屬性和原型屬性

person1.name = "Greg";
alert(person1.name);  //"Greg"——來自實例 
alert(person2.name);  //"Nicholas"——來自原型

delete person1.name; alert(person1.name); //"Nicholas"——來自原型

咱們看到訪問實例屬性的時候,優先級是實例屬性-->原型屬性,刪除屬性的時候優先級也是如此;

實例上有該屬性,就直接拿實例的該屬性,沒有的話就去原型上找.

3.3.2 hasOwnProperty() 判斷屬性是否是來自於實例

var person1 = new Person();
var person2 = new Person();
alert(person1.hasOwnProperty("name"));  //false
person1.name = "Greg";
alert(person1.name); //"Greg"——來自實例 
alert(person1.hasOwnProperty("name")); //true

實例的原型屬性不可枚舉:

var keys = Object.keys(Person.prototype);
alert(keys);       //"name,age,job,sayName"

var p1 = new Person(); p1.name = "Rob"; p1.age = 31; var p1keys = Object.keys(p1); alert(p1keys); //"name,age"
相關文章
相關標籤/搜索