【JS】面向对象之创建对象(一)

175 阅读3分钟

一、几种比较基础的方式

  1. 使用 {} 创建
        /**
        使用{}创建对象,等同于 new Object();
        **/
        var o = {};

        o.name = 'jack';
        o.age = 20;

        o.sayName = function(){
            alert(this.name);
        }
  1. Object构造函数
        // 使用 new Object() 创建对象
        var o = new Object();
        o.name = "zhangsan";
        o.sayName = function(){
            alert(this.name);
        }

        o.sayName();
  1. 对象字面量
        var person = {name: 'zhang', age:20}

以上几种方式的缺点:

1.代码冗余
    说人话:每次创建新的实例,都要再从头到尾写一遍代码
2.方法不能共享
    说人话:每创建一个实例,就要创建一个属于该实例的方法

二、工厂模式

        // 使用工厂模式创建对象
        // 定义一个工厂方法
        function createObject(name){
            var o = new Object();
            o.name = name;
            o.sayName = function(){
                alert(this.name);
            };
            return o;
        }

        var o1 = createObject('zhang');
        var o2 = createObject('li');
        alert(o1.sayName===o2.sayName);   //false

工厂模式的优缺点:

优点:解决了代码冗余
    说人话:每次创建新的实例,只需要调用一次方法即可
缺点:1. 方法不能共享 2. 没有解决对象识别问题
    说人话:还是没有解决:每创建一个实例,就要创建一个属于该实例的方法
    说人话:创建对象的类型都是object,过于宽泛

三、构造函数模式

        /**
         *  构造函数模式创建对象
         **/
        function Person(name){
            this.name = name;
            this.sayName = function(){
                alert(this.name);
            };
        }

注意:

  1. 规范:构造函数的函数名大写,和其他非构造函数区分
  2. 构造函数也是函数,只不过可以用来创建对象
  3. 任何函数,只要通过new来调用,那它就可以作为构造函数;如不用new,那么和普通函数毫无差异。
    var personA = new Person('zhangsan');

调用构造函数经历了:

  1. 创建一个新对象(开辟了新的空间,用于存储新对象)
  2. 将构造函数作用域赋给新对象(this指向了这个新对象)
  3. 执行构造函数代码(为personA添加了name属性,并赋值)
  4. 返回新对象(personA)

注意:

  1. 实例personA的类型是Person
    typeof personA == Person  //true
  1. 实例personA有一个constructor属性,指向了Person
    console.log(personA.constructor) //Person

构造函数模式的优缺点:

优点:解决了工厂模式的对象识别问题
    说人话:通过new创建的实例有了具体、确定的类型,不再是模糊的object了
缺点:方法不能共享 
    说人话:还是没有解决:每创建一个实例,就要创建一个属于该实例的方法

四、改进的构造函数模式

    function Person(name){
        this.name = name;
        this.sayName = sayName
    }
    
    function sayName() {
        alert(this.name);
    }
    
    var person1 = new Person('zhangsan')
    var person2 = new Person('lisi')
    
    console.log(person1.sayName == person2.sayName)  //true

改进构造函数模式的优缺点:

优点:解决了方法共享问题
    说人话:不同实例可以共享一个sayName方法
缺点: 破坏了构造函数的封装性
    说人话:sayName方法本应是Person实例专有的,但是改进构造函数中,
            不但Person的实例可以调用sayName(),其他对象也可以调用。

五、总结

根据如上几种模式,我们理想的创建对象方式:属性私有,方法公用。

重要的事情说三遍:

属性私有,方法公用!

属性私有,方法公用!

属性私有,方法公用!

个人认为这句话很重要,是因为后面原型模式的出现,以及构造+原型模式组合使用,都是意在达成此目的。 把握住属性私有,方法公用的主线,就会理解原型模式的出现,以及它解决的问题。

Thanks for Reading......