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

13 篇文章 1 订阅
7 篇文章 0 订阅

《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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值