全面理解Javascript的面向对象(二)--创建对象与继承
2017-04-18 20:50
615 查看
在前文全面理解Javascript的面向对象(一)中详细介绍了面向对象的主要知识点,可以帮助大家很细致的了解js面向对象的概念,本文作为补充,主要从对象的构建和继承的方式两方面进行分析。
缺点:没有解决对象的识别问题,即怎样知道一个对象的类别。于是,新的模式:构造函数模式出现了。
使用构造函数方法创建对象经历了四个过程:
- 创建新对象
- 将构造函数作用域赋给新对象(this指向了新对象)
- 执行构造函数的方法(为新对象添加属性)
- 返回新对象
自定义的构造函数可将它的实例标识为特定的类型,这是胜过工厂模式的地方
缺点:每个方法在每个实例上多次创建。这个问题可以通过原型模式解决。
更简单的原型语法:
将一个原型对象等于另一个实例,这个原型对象包含一个指向另一个原型的指针,相应的,另一个原型也包括一个指向构造函数的指针,这样层层递进,构成了实例与原型的链条
缺点:创建子类型的实例时,不能向超类型的构造函数中传递参数。
与原型链模式相比,借用构造函数的最大优势是子类可以向超类中传递参数。
缺点:方法都在构造函数中定义,因此函数复用就无从谈起,超类型的原型中定义的方法,对子类型而言不可见。因此借用构造函数的模式很少单独使用。
思路是
- 使用原型链实现对原型属性和方法的继承;
- 使用借用构造函数的方法实现对实例属性的继承。
这样,通过在原型上定义方法实现函数复用,又能够保证对每个实例有自己的属性。
组合模式是javascript中最常用的模式。
在object()函数内部,先创建一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的一个新实例。object()对传入的对象进行了一次浅复制。
在ES5中新增Object.create()方法,规范了原型继承。这个方法又两个传入的参数,一个是对象,另一个是==可选==的额外定义的属性。
一、创建对象主要的几种方式
1 工厂模式
工厂模式抽象了创建具体对象的过程,用函数封装以特定接口创建对象的细节。function createPerson(name,age,job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function () { alert(this.name); } return o; } var person1 = createPerson("Nike",21,"Doctor"); var person2 = createPerson("Frank",21,"Manager");
缺点:没有解决对象的识别问题,即怎样知道一个对象的类别。于是,新的模式:构造函数模式出现了。
2 构造函数模式
像Object、Array这样的原生构造函数,在运行时就会自动创建。此外也可以自定义构造函数,从而定义自定义对象类型的属性和方法。function Person(name,age,job) { this.name = name; this.age = age; this.job = job; this.sayName = function () { alert(this.name); } } var person1 = new Person("Nike",21,"Doctor"); var person2 = new Person("Frank",21,"Manager");
使用构造函数方法创建对象经历了四个过程:
- 创建新对象
- 将构造函数作用域赋给新对象(this指向了新对象)
- 执行构造函数的方法(为新对象添加属性)
- 返回新对象
自定义的构造函数可将它的实例标识为特定的类型,这是胜过工厂模式的地方
alert(person1 instanceof Object); //ture alert(person1 instanceof Person); //ture alert(person2 instanceof Object); //ture alert(person2 instanceof Person); //ture
缺点:每个方法在每个实例上多次创建。这个问题可以通过原型模式解决。
3 原型模式
function Person() { } Person.prototype.name = 'frank'; Person.prototype.age = 21; Person.prototype.sayName = function () { alert(this.name); } var person1 = new Person(); person1.sayName(); var person2 = new Person(); person2.sayName(); alert(person1.sayName == person2.sayName); //true
更简单的原型语法:
function Person() { } Person.prototype = { constructor : Person, name:'frank', age:29, sayName:function () { alert(this.name); } };
4 组合使用构造函数模式和原型模式
构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本,同时又共享着方法的引用,最大限度节省内存。function Person(name,age,job) { this.name = name; this.age = age; this.job = job; } Person.prototype = { constructor : Person, sayName : function () { alert(this.name); } } var person1 = new Person("Nike",21,"Doctor"); var person2 = new Person("Frank",21,"Manager");
二、继承的实现方式
1 原型链
如果对象无法相应某个请求,他会把这个请求委托给他的构造器的原型对象。将一个原型对象等于另一个实例,这个原型对象包含一个指向另一个原型的指针,相应的,另一个原型也包括一个指向构造函数的指针,这样层层递进,构成了实例与原型的链条
function SuperType() { this.property = true; } SuperType.prototype.getSuperType = function () { return this.property; } function SubTpye() { this.subproperty = false; } SubTpye.prototype = new SuperType(); var ins = new SubTpye(); alert(ins.getSuperType());
缺点:创建子类型的实例时,不能向超类型的构造函数中传递参数。
2 借用构造函数
在子类型构造函数中调用超类型构造函数。function SuperType() { this.colors = ['red','blue','green']; } function SubTpye() { SuperType.call(this); } var ins1 = new SubTpye(); ins1.colors.push("black"); alert(ins1.colors); //'red','blue','green','black' var ins2 = new SubTpye(); alert(ins2.colors); //'red','blue','green'
与原型链模式相比,借用构造函数的最大优势是子类可以向超类中传递参数。
function SuperType(name) { this. name = name; } function SubTpye() { SuperType.call(this,"frank"); } var ins1 = new SubTpye(); alert(ins1.name); //'frank'
缺点:方法都在构造函数中定义,因此函数复用就无从谈起,超类型的原型中定义的方法,对子类型而言不可见。因此借用构造函数的模式很少单独使用。
3 组合继承
组合继承是将原型链和借用构造函数的方法结合到一起。思路是
- 使用原型链实现对原型属性和方法的继承;
- 使用借用构造函数的方法实现对实例属性的继承。
这样,通过在原型上定义方法实现函数复用,又能够保证对每个实例有自己的属性。
function SuperType(name){ this.name = name; this.colors = ["red","blue","green"]; } SuperType.prototype.callName = function(){ alert(this.name); } function SubType(name,age){ SuperType.call(this,name); this.age = age; } SubType.prototype = new SuperType(); SubType.prototype={ constructor:SubType, callAge:function(){ alert(this.age); } } var ins1 = new SubType("nike",29); ins1.colors.push("black"); console.log(ins1.colors); console.log(ins1.callName()); console.log(ins1.callAge());
组合模式是javascript中最常用的模式。
4 原型继承
在上一篇博文全面理解Javascript的面向对象(一)中,介绍过,原型继承的本质是基于原型链的委托机制。function object(o){ function F(){} F.prototype = o; return new F(); }
在object()函数内部,先创建一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的一个新实例。object()对传入的对象进行了一次浅复制。
var Person = { name:"nike", friends:["frank","lucy"]; } var another = object(Person); another.gentle = "male"; another.friends.push("mike");
在ES5中新增Object.create()方法,规范了原型继承。这个方法又两个传入的参数,一个是对象,另一个是==可选==的额外定义的属性。
var another1 = Object.create(Person); another.gentle = "male"; var another2 = Object.create(Person,{ name:{ value:"Greg" } });
相关文章推荐
- JavaScript面向对象中的属性,对象创建,继承
- javascript面向对象中的对象创建、继承、封装等实现方式
- javascript 面向对象的对象创建与继承
- JAVASCRIPT 对象的创建和对6种继承模式的理解和遐想
- Javascript面向对象全面剖析 —创建对象
- 全面理解面向对象的 JavaScript
- 学习javascript面向对象 理解javascript对象
- (13)javascript 面向对象 创建对象
- javascript面向对象(一)-创建对象
- 全面理解Javascript中Function对象的属性和方法
- JavaScript构造函数+原型创建对象,原型链+借用构造函数模式继承父类练习
- 深入理解JavaScript系列(47):对象创建模式(上篇)
- 全面理解面向对象的 JavaScript
- 理解javascript对象继承
- 轻松学习JavaScript十二:JavaScript基于面向对象之创建对象(二)
- JavaScript中的面向对象(一)——创建自定义对象
- 理解Javascript_06_理解对象的创建过程
- 【JavaScript高级程序设计】对象的创建与继承
- javascript中用构造函数创建对象以及基类与子类间的继承
- javascript创建对象,以及实现继承的方法