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

最近找实习,上一场电话面试突如起来,没有一点点防备。。。问了一些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方法之外没有办法再访问原始数据成员。
这种安全模式适用于某些安全环境。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值