1.对象适合于收集和管理数据,容易形成树型结构。 Javascript包括一个原型链特性,允许对象继承另一对象的属性。正确的使用它能减少对象的初始化时间和内存消耗。 2.函数它们是javascript的基础模块单元,用于代码复用、信息隐藏和组合调用。函数用于指定对象的行为。一般来说,编程就是将一组需求分解成一组函数和数据结构的技能。 3.模块我们可以使用函数和闭包来构造模块。模块是一个提供接口却隐藏实现状态和实现的函数或对象。
1.自定义类型--构造函数模式(伪类模式)
在基于类的系统中,对象是这样定义的:使用类来描述它是什么样的。假如建筑是基于类的系统,则建筑师会先画出房子的蓝图,然后房子都按照该蓝图来建造。
在使用自定义类型模式实现继承的时候,我们只需要将参数传递给构造函数,然后将参数挂载在实例对象上。其他关于实例对象的方法都不用传递参数,因为通过 实例对象调用的方法内部的this都可以访问到该参数。挂载在实例this对象上的变量称为实例变量。
组合--继承
function Person (name, age, job) { // 实例变量 this.name = name; this.age = age; this.job = job; } Person.prototype.sayName = function () { alert(this.name); } var person1 = new Person('Nicholas', 29, 'Software Engineer'); var person2 = new Person('Greg', 27, 'Doctor'); function SuperType (name) { this.name = name; this.colors = ['red','blue', 'green']; } SuperType.prototype.sayName = function () { console.log(this.name); } function SubType (name, age) { // 继承属性 SuperType.call(this,name); this.age = age; } // 继承方法 SubType.prototype = new SuperType(); SubType.prototype.sayAge = function () { console.log(this.age) } var instance1 = new SubType('Nicholas', 29); instance1.colors.push('black') console.log(instance1.colors); instance1.sayName(); instance1.sayAge(); var instance2 = new SubType('Greg', 27) console.log(instance2.colors); instance2.sayName(); instance2.sayAge();
在继承属性和继承方法上,我们一共调用了两次超类构造函数,当通过new调用超类构造函数创建子类构造函数的原型时,有一个问题,子类构造函数的原型对象现在便是超类构造函数的实例,因此也会有在超类构造函数为实例对象this添加的属性,只是值为undefined而已,也就是说通过new调用超类构造器函数来更改子类改造器的原型时,那么在子类构造器的原型上便会有多余的属性。这便造成了浪费。而我们需要的其实只是,子类构造器的原型能够继承超类构造器原型的方法而已。因此我们需要的,
1.创建一个子类构造器原型对象。
2.此子类构造器原型继承自超类构造器的原型。
3.因为我们在1中改写了子类构造器的原型对象,也就是重新创建了原型对象,因此我们需要在新创建的原型对象上添加constructor属性并将其赋值为子类构造器函数。
将上面的代码改写一些,如下所示。
关于constructor属性:只在构造器函数的原型上才有的属性并指向该构造器,改写了的原型对象默认是没有constructor属性的。
寄生组合式--继承
function inheritPrototype (subType,superType) { var prototype = Object.creat(superType.prototype); prototype.constructor = subType; subType.prototype = prototype; }; function SuperType (name) { this.name = name; this.colors = ['red', 'blue', 'green']; } SuperType.prototype.sayName = function () { console.log(this.name); } function SubType(name, age) { //继承属性 SuperType.call(this,name); this.age = age; } //继承方法 inheritPrototype(SubType,SuperType); SubType.prototype.sayAge = function () { console.log(this.age); } var instance = new SubType();
通过隐藏那些所谓的prototype操作细节,现在看起来没那么怪异了。但是否真的有所发现:
没有私有环境,所有属性都是公开的。无法访问父类的方法。难以调试
2.原型
在一个纯粹的原型模式中,我们会摈弃类,转而专注对象。基于原型的继承相比基于类的继承在概念上更简单:一个新对象可以继承一个旧对象的属性。你通过构造有用的对象开始,接着可以构造更多和那个对象类似的对象。这就可以完全避免把一个应用拆解成一系列嵌套抽象类的分类过程
在基于原型的系统中,我们创建的对象,看起来要像我们想要的所有这种类型的对象那样,然后告诉javascript引擎,我们想要更多像这样的对象。如果建筑是基于原型的,建筑师会先建一所房子,然后将房子都建成像这种模样的。
方法Object.creat()作为new操作符的替代方案,使用它来创建javascript对象时,能增添一种更像是基于原型的感觉。