首页 > 技术文章 > js 创建对象

lilei-site 2019-11-05 18:42 原文

创建对象可能首先想到的就是字面的形式,比如这样的

        <!--字面量-->
        var obj1 = {
            name: "张三",
            age: 18
        }              

但是这样创建对象,如果创建多个类似的对象就会有冗余代码,所以就有了各种模式来创建对象

第一种  工厂模式

function createPerson(name,age) {
            var o = new Object();
            o.name = name;
            o.age = age;
            o.say = function(){
                alert(this.name);
            }
            return o;
        }
        
        var person1 =  createPerson("lisi",21);   //instanceof无法判断它是谁的实例,只能判断他是对象,构造函数都可以判断出
        var person2 =  createPerson("wangwu",18);
        console.log(person1 instanceof Object);

这样虽然解决了代码的冗余,但是无法判断一个对象的类型

 

第二种  构造函数模式

 

/*构造函数模式*/
        function Person(name,age) {
            this.name = name;
            this.age = age;
            this.say = function(){
                alert(this.name);
            }
        }
        var person1 = new Person("lisi",21);
        var person2 = new Person("lisi",21);
        console.log(person1 instanceof Object); //true
        console.log(person1 instanceof Person); //true
        console.log(person2 instanceof Object); //true
        console.log(person2 instanceof Person); //true
        console.log(person1.constructor);      //constructor 属性返回对创建此对象的数组、函数的引用

这个模式利用了new执行函数的时候会创建一个对象,自动返回这个对象,相比工厂模式没有显示的创建对象,直接赋予了this对象,没有return语句

但是这样创建对象有一个缺点,就是相同的函数创建了两个 alert(person1.say == person2.say)为false,这个就没必要,所以就有了原型模式的出现

 

第三种  原型模式

 

     /*原型模式*/
        function Person() {
        }
        Person.prototype.name = "张三";
        Person.prototype.age = 21;
        Person.prototype.say = function(){
            alert(this.name);
        };
        console.log(Person.prototype);
        
        var person1 = new Person(); 
        console.log(person1.name); 
        
        var person2 = new Person();
        person2.name = "李四";
        console.log(person2);
        console.log(person2.age);
     

 

结果为

 

 使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。换句话说,不必再构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中。

如:alert(person1.say == person2.say);  //true

这种方法感觉就写了很多遍Person.prototype,代码有冗余,所以可以这样写

 

        function Person() {
        }
        Person.prototype = {
            name : "张三",
            age : 21,
            say : function(){
                alert(this.name)
           }
        }

 

但是这样就导致了constructor属性没有了

 

 但是还是有方法可以解决,方法如下:

        function Person() {
        }
        Person.prototype = {
            name : "张三",
            age : 21,
            say : function(){
                alert(this.name)
           }
        }
        Object.defineProperty(Person.prototype, "constructor",{
            enumerable:false,
            value:Person
        })

结果如下:

 

 说到这里,原型模式还是有一个很大的问题,就是对于引用类型值的属性的时候,因为其共享的本质,造成了如下问题

 

 

 

 所以一般不会有人单独使用原型模式创建对象

 

第四种  组合使用构造函数模式和原型模式

创建自定义类型的最常见的方式就是这种组合模式了,因为这种组合模式可以说是集两种模式之长

代码如下

function Person(name,age) {
            this.name = name;
            this.age = age,
            this.friends = ['李四','小二'];
        }
        Person.prototype = {
            constructor: Person,
            say : function(){
                alert(this.name)
           }
        }
        var person1 = new Person('person1',18);
        var person2 = new Person('person2',20);
        
        person1.friends.push('王五');
        console.log(person1.friends);//李四,小二,王五
        console.log(person2.friends);//李四,小二,王五
        console.log(person1.friends === person2.friends);//false
        console.log(person1.say === person2.say);//true

 

 

 这种构造函数和原型模式混合的模式,可以说是现在最广泛的创建自定义类型的方法

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

推荐阅读