您的位置:首页 > Web前端 > JavaScript

[置顶] 《JS高级程序设计》第6章读书笔记:创建对象(一)之工场模式和构造函数模式

2017-08-20 11:10 555 查看
《JS高级程序设计》第6章的读书笔记

创建对象(一)工场模式和构造函数模式

创建对象(二)原型模式和组合模式

创建对象(三)再探原型

对象继承(一)原型链

对象继承 (二)借用构造函数和组合继承

对象继承(三)原型式继承和寄生式继承

对象继承(四)寄生组合式继承

1 前言

JS在诞生之初,正值Java火热,其作者创造JS是模仿Java,在很多地方又做了简化,被人称为玩具语言。但是它在创造对象,继承这方面又是如此复杂。就继承而言,就有6种方式。这是在我学习的其他语言,如Python, C++, Java中,我未曾见过的。不得不说,这真的很神奇。

本文是要讲的创建对象的3种方式:工厂模式,构造函数模式,原型模式和组合模式(组合构造函数模式和原型模式)。

这些内容我是第二遍看了,但是第一遍看是在今年3月份,我刚开始学真正的JS的时候,那时候并没有看得太仔细。

当然还有其他方式,但是从《JS高程》这本书看出来,这4种方式是最重要的。

2 工厂模式

《JS高程》是这么描述工厂模式的:用函数来封装以特定接口创建对象的细节。

嗯,很理论的一句话。

简单地说,在工厂模式下,对象的创建和属性的赋值都是在一个函数中完成的。

其基本模式的代码如下:

function createPerson(name){
var o = new Object();
o.name=name;
o.sayName=function(){
return this.name;
}
return o;
}
var p1= createPerson('achao');
var p2= createPerson('yujie');


我们可以看到对象
o
的创建,及其属性
name
的创建都是在
createPerson
中完成的。

书上说(工厂模式)“没有解决对象识别的问题”。(OS:没有问题的话,这篇博文就可以在这里结束了。

为什么呢。我们可以看到对象
o
的类型
Object
的使用是在函数内,当你调用
createPerson
这个函数时,你是看不到里面的细节的,这就是书上说“没有解决对象识别的问题”d的原因。当然
Object
可以换成任何其他类型的对象,但这不改变结论。

上述提到的问题在下一节的
构造函数模式
中被解决。

3 构造函数模式

ES6之前没有
class
的范畴,所以ES5是通过
构造函数
创建对象。构造函数与一般的函数并没有区别,被用作创建对象,其自然被称为构造函数。

书上对此是这么说的:“不存在定义构造函数的特殊语法,只要通过new操作符来调用,那它就可以作为函数;而额任何函数,如果不通过new操作符调用,那它跟普通函数也不会有什么两样。”

构造函数模式创建对象的基本代码是这样的:

function Person(name) {
this.name = name;
this.getName = function() {
return this.name;
}
}
var p1 = Person('achao');
var p2 = Person('yujie');


与工厂模式相比,构造函数模式有以下不同:

没有显式地创建对象

直接将属性和方法赋给了this对象

没有return语句

以上3点关键之处在于new操作符,使用new操作符调用构造函数会经历以下4个步骤

创建一个新对象

将构造函数的作用域赋给新对象(因此this就指向了这个新对象)

执行构造函数中的代码(为这个新对象添加属性)

返回新对象

之前提到:工厂模式没有解决对象识别的问题。

这个问题在构造函数模式中被解决:

var p1 = Person('achao');


对象的类型:Person是被暴露出来的。

console.log(p1 instanceof Person); // true


3-1 构造函数的问题

书上说:“构造函数的主要问题是:每个问题都要在每个实例上创建一遍”

this.getName = function() {
return this.name;
}


对象p1和p2各自包含一个不同的getName方法。

console.log(p1.getName == p2.getName); //false


但是,从语义上讲:这类方法不应该被共享

当然,这个问题是有解决方法的。

function Person(name) {
this.name = name;
this.getName = getName;
}

function getName() {
return this.name;
}

var p1 = new Person('achao');
var p2 = new Person('yujie');
console.log(p1.getName == p2.getName);//true


通过将函数的定义转移到构造函数外部,然后在构造函数内部引用外部函数即可。

如此,p1和p2共享了
getName
函数。这注意,
getName
函数中的
this
指向的对象是执行时的对象,而非绑定的对象,也就是构造函数内部this绑定的
被新创建的对象
。所以
getName
函数能获取p1,p2各自的
name


但是这样造成了两个问题

在全局作用域中定义的函数只能被某个对象调用,这名不副实。

全局函数没有封装性可言

问题是必须的,否则就没有下一节讲的
原型模式
什么事了。

下一篇博文地址:

《JS高级程序设计》第6读书笔记:创建对象(二)原型模式和组合模式

http://blog.csdn.net/huangpin815/article/details/77428630
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐