【六】深入理解javascript创建对象的七种方式

    xiaoxiao2021-03-25  134

    最近找实习,上一场电话面试突如起来,没有一点点防备。。。问了一些javascript的题目感觉答得渣渣渣,然后又捡起《javascript高级程序设计》开始复习javascript基础== 本节复习面向对象的程序设计,详细记录的创建对象的七种方式,从工厂模式到组合模式,从动态原型式到稳妥构造函数模式。

    创建对象的最简单方式是使用对象字面量,或使用Object构造函数

    var obj = { name: "caesar", age: 20, showName: function() { console.log(this.name); } }

    使用这种方式创建对象很简单,但是存在一个问题:如果需要创建很多对象,这些对象的属性和方法相同,通过对象字面量和Object构造函数创建对象,无疑会有大量的重复代码。 为解决重复代码的问题,由此引入第一种创建对象的方法:工厂模式。

    工厂模式

    // 工厂模式 function createPerson(name,age) { var obj = new Object(); obj.name = name; obj.age = age; obj.showName = function() { console.log(this.name) }; return obj; } var person1 = createPerson("haha",20); person1.showName(); console.log(person1 instanceof Person); console.log(person1.constructor == Person);

    工厂模式很好理解,从名字理解就是作为一个生产对象的工厂来创建对象,因此去除了重复性的代码。 但是工厂模式同样存在一定的问题:对象是通过工厂创建的,无法知道对象的类型。由此引入下一个方法,构造函数模式。

    构造函数模式

    function Person(name,age) { this.name = name; this.age = age; this.showName = function() { console.log(name); } } var person1 = new Person("caesar",20); person1.showName(); console.log(person1 instanceof Person); console.log(person1.constructor == Person);

    任何函数通过new操作符调用都可以作为构造函数,不通过new调用那就是普通的函数,通过new创建实例,经历了以下四步: 1. 创建一个新对象 2. 将构造函数作用域赋给新对象 3. 执行构造函数中的代码 4. 返回新对象

    通过构造函数模式解决了工厂模式存在的问题:不能识别对象类型。创建的实例有一个constructor属性,指向Person。当然,通过instanceof检测对象类型更靠谱。

    构造函数模式同样存在一定问题:每个方法都会在每个实例上重现创建一遍,然而其实这些方法是可以公用的。

    // 函数也是对象,每定义一个函数相当于实例化一个对象 this.showName = new Function("console.log(name)"); // 不同实例的同名函数是不相等的 var person1 = new Person("caesar",20); var person2 = new Person("hahaha",22); // 打印false console.log(person1.showName == person2.showName);

    为了解决这个问题,又引入了原型模式。

    原型模式

    function Person() { } Person.prototype.name = "caesar"; Person.prototype.age = 20; Person.prototype.showName = function() { console.log(this.name) } var person1 = new Person(); var person2 = new Person(); person1.showName(); // 打印true console.log(person1.showName == person2.showName);

    每个函数又一个prototype属性,prototype是一个指针,指向一个对象,该对象包含可以被某些类型的实例共享的属性和方法。使用原型对象可以让所有的实例共享原型对象的属性和方法,因而解决了在构造函数模式中存在的问题。

    关于原型对象

    暂略


    原型模式要注意的几点

    暂略。。。


    原型模式同样也存在问题: 1.没有为构造函数传递参数,所有实例在默认情况下都将取得相同值。 2.最重要的问题是,原型中的属性和方法是共享的,这很不错,对于某些共享的方法和基本值的属性来说。但是对于引用类型的值来说,就存在严重的问题了。

    function Person() { } Person.prototype.friends = ['aaa','bbb']; var person1 = new Person(); var person2 = new Person(); person1.friends.push("ccc"); // 打印[ 'aaa', 'bbb', 'ccc' ] console.log(person1.friends); // 打印[ 'aaa', 'bbb', 'ccc' ] console.log(person2.friends);

    为了解决这个问题,又引入了下面的这个模式:组合模式

    组合模式

    组合使用原型模式和构造函数模式,集两种模式的优点,构造函数模式用来定义实例属性,原型模式用来定义共享属性。

    function Person(name,age) { this.name = name; this.age = age; this.friends = ["aaa"]; } Person.prototype.showFriends = function() { console.log(this.friends); } var person1 = new Person("caesar",19); var person2 = new Person("hahaha",20); person1.friends.push("bbb"); person1.showFriends();// [ 'aaa', 'bbb' ] person2.showFriends();// [ 'aaa' ]

    组合模式是使用最广泛的模式。

    再坚持一下,还有3个模式要写==

    动态原型模式

    对于组合模式,可能会有人觉得困惑:构造函数和原型相互独立,感觉怪怪得? 为解决这种困惑,从而产生的动态原型模式:将所有信息封装在构造函数中。在构造函数中初始化原型。

    function Person(name,age) { this.name = name; this.age = age; if(typeof this.showName != "function") { Person.prototype.showName = function() { console.log(this.name); } } } var person1 = new Person("caesar",20); person1.showName();

    比较容易理解,不解释。

    寄生构造函数模式

    function Person(name,age) { var obj = new Object(); obj.name = name; obj.age = age; obj.showName = function() { console.log(this.name); } return obj; } var person1 = new Person("caesar",20); person1.showName();

    顾名思义。。。创建对象的代码寄生在构造函数里面。。。 构造函数中返回的对象与构造函数和构造函数原型没有关系,因而无法确定对象类型。 但是这种模式在某些特殊情况下可以使用,但一般情况下尽量不要使用这种模式。

    稳妥构造函数模式(安全模式)

    与寄生构造函数模式类似,但是有两点不同: 1.新创建对象的实例方法不引用this 2.不使用new操作符调用构造函数

    function Person(name,age) { var obj = new Object(); obj.showName = function() { console.log(name); } return obj; } var person1 = Person("caesar",20); person1.showName();

    除了调用showName方法之外没有办法再访问原始数据成员。 这种安全模式适用于某些安全环境。

    转载请注明原文地址: https://ju.6miu.com/read-6356.html

    最新回复(0)