Javascript建立對象幾種方法解析

Javascript建立對象幾種方法解析

Javascript面向對象編程一直是面試中的重點,將本身的理解整理以下,主要參考《Javascript高級程序設計 第三版》,歡迎批評指正。javascript

經過字面量形式,建立對象:

var person_1 = {
            name: "userName",
            age: 20
        }

工廠模式建立對象

經過一個構造函數接收參數的方式構造對象,可無數次調用這個函數,經過改變參數構造不一樣的對象
function createPerson(name,age){
            var o = new Object();//建立一個空的對象 -- 原料

            o.name = name;
            o.age = age;
            o.sayName = function(){       //給對象屬性賦值 -- 加工過程
                alert(this.name)
            }

            return o; //返回加工後的對象 -- 出廠
        }
        var leo = createPerson('Leo',30);
        leo.sayName(); //"Leo"
        var cherry = createPerson('Cherry',20);
        cherry.sayName(); //"Cherry"
缺點:工廠模式建立的對象,沒法判斷其類型

構造函數模式:

相似Array,Object這種原生的構造函數,咱們能夠經過建立自定義的構造函數,從而定義自定義對象的類型和方法
function Person(name,age){
            this.name = name;
            this.age = age;
            this.sayName = function(){
                alert(this.name);
            }
        }
        var leo = new Person('Leo',18);
        var cherry = new Person('Cherry',25);
        leo.sayName();
        cherry.sayName();
  1. 與工廠模式對比,幾點不一樣:沒有現實的建立空對象;直接將屬性和方法賦值給this;不須要return
  2. 經過New操做符建立Person對象的新實例:①建立一個新的對象 ②this指向這個新對象(做用域)③執行構造函數中的代碼,對新對象添加屬性和方法④返回新對象
  3. 經過instanceof檢測對象類型,發現經過Person構造函數建立的對象,即便Person類的實例,又是Object對象的實例 - 建立自定義的構造函數代表能夠將它的實例標識爲一種特定的類型
alert(leo instanceof Person); //true 
        alert(leo instanceof Object); //true 全部對象都繼承自Object
  1. 區分構造函數和普通函數
    ①. 任何函數經過new操做符調用,就可作爲構造函數
    ②. 自定義的構造函數,不經過new調用,與普通函數沒有區別
Person('window',100);//直接調用,至關於將Person類的屬性方法直接添加到了this上
        window.sayName(); //window
  1. 缺點:經過構造函數,每一個方法都要在實例上從新建立一遍,每一個實例的sayName方法,至關於執行this.sayName = new Function("alert(this.name)")單首創建出來的
alert(leo.sayName==cherry.sayName);//false

原型模式:

  1. 建立的每一個函數都有prototype屬性,這個屬性指向一個其屬性和方法由某個特定類的全部實例共享的對象,利用prototype,咱們就可將定義對象實例的信息放在原型對象中,沒必要在構造函數中定義。
function Person(){} //構造函數變成空
        Person.prototype.name = 'Leo';
        Person.prototype.age =30;
        Person.prototype.sayName = function(){
            alert(this.name);
        }
        var person1 = new Person();
        var person2 = new Person();
        alert(person1.sayName==person2.sayName);//true 將sayName方法定義在Person的prototype屬性中,可由多個不一樣的實例共享
        //簡化寫法:
        function Person() { } //構造函數變成空
            Person.prototype = {
                name: 'Leo',
                age: 30,
                sayName: function () {
                    alert(this.name);
            }
         }    
         var person1 = new Person();
         var person2 = new Person();
  1. 只要建立一個新函數,就會爲該函數建立一個prototype屬性,這個屬性指向原型對象。在咱們建立的對象person1和person2中都包含一個內部屬性,該屬性指向Person.prototype,所以兩個實例均可以調用原型中的sayName()方法。Object.getPrototypeOf()方法能夠更方便的取得一個對象的原型.
alert(Person.prototype.isPrototypeOf(person1));//true
      alert(Person.prototype.isPrototypeOf(person2));//true
      alert(Object.getPrototypeOf(person1)==Object.getPrototypeOf(person2));//true
  1. 給一個對象添加一個屬性,這個屬性會屏蔽原型對象中存儲的同名屬性,經過hasOwnProperty()方法可判斷是實例對象中的屬性,仍是原型中的屬性;經過in運算符,能夠判斷在對象上可否找到某屬性,而不區分是實例屬性仍是原型屬性,for in循環中只會遍歷可訪問、可枚舉的屬性。
person1.name='Nancy';
        alert(person1.name);//Nancy
        alert(person1.hasOwnProperty("name"));//True 實例對象上的屬性
        alert(person2.hasOwnProperty("name"));//false 原型中的屬性
        alert("name" in person1);//true
        alert("name" in person2);//true
        for(key in person1){
            alert(`${key}:${person1[key]}`)
        }
  1. 原型模式的缺點:①缺乏向構造函數傳遞初始化參數這一環節,使得同一個對象的全部實例在默認狀況下都會取得相同的屬性值。②在實例中修改引用屬性的值,會影響其餘的實例。
function Newperson(){
        }

        Newperson.prototype = {
            constructor : Newperson,
            name:"Tony",
            age:30,
            job:"Developer",
            friends:['Leo','Cherry'],
            sayName:function(){
                alert(this.name);
            }
        }

        let newPerson1 = new Newperson();
        let newPerson2 = new Newperson();
        alert(newPerson1.friends);//Leo, Cherry
        alert(newPerson2.friends);//Leo, Cherry
        newPerson1.friends.push('Mai');//friends屬性引用數組在Newperson.prototype而非newPerson1中,newPerson1.friends和newPerson2.friends指向的是同一個引用
        alert(newPerson1.friends);//Leo, Cherry, Mai
        alert(newPerson2.friends);//Leo, Cherry, Mai
        alert(newPerson1.friends === newPerson2.friends);//true

組合使用構造函數模式和原型模式

  1. 組合使用構造函數模式和原型模式是建立自定義類型的常見方式,構造函數用於定義實例屬性,原型模式用於定義方法和共享屬性。
function Person(name,age,job){
            this.name = name;
            this.age = age;
            this.job = job;
            this.friends = ["Leo","Cherry"];
        }

        Person.prototype = {
            constructor:Person,
            sayName:function(){
                alert(`${this.name} is a ${this.job}.`);//公共方法
            }
        }

        let person1 = new Person('Mai',18,'actor');
        let person2 = new Person('Bob',25,'developer');
        person1.sayName();
        person2.sayName();
        alert(person1.friends == person2.friends);//false friends屬性在構造函數中定義,不在原型中,兩個實例不會相互影響
        person1.friends.push('Tony');
        person2.friends.push('Melody');
        alert(person1.friends);//Leo, Cherry, Tony
        alert(person2.friends);//Leo, Cherry, Melody
相關文章
相關標籤/搜索