资讯专栏INFORMATION COLUMN

对象的创建继承

UCloud / 2735人阅读

摘要:一创建一个对象起因用或对象字面量创建对象会产生大量的重复代码而且只能通过变量名来区分不同的对象没有记录对象的类型例如创建对象字面量创建对象工厂模式创建对象工厂模式解决了相似代码重复书写的问题好处中无法创建类为了模仿类的创建方式抽象具体对象的

一.创建一个对象

起因.................
用Object或对象字面量创建对象会产生大量的重复代码,而且只能通过变量名来区分不同的对象,没有记录对象的类型
例如:

 //Object创建对象
 var student = new Object();
 student.name = "s";
 student.age = "20";
 var student1 = new Object();
 student1.name = "s1";
 student.age = "20";
 //字面量创建对象
 var student = {
   name: "s",
   age: "23"
 }
 var student1 = {
   name: "s",
   age: "23"
 }
1.工厂模式创建对象

工厂模式解决了相似代码重复书写的问题

//好处:js中无法创建类,为了模仿类的创建方式,抽象具体对象的创建过程;
//缺点:工厂模式创建的对象是通过普通函数调用实现的,没有解决标识对象类型的问题,无法区分对象的类型,
  function person(name) {
   var o = new Object();
   o.name = name;
   o.sayName = function() {
     console.log(this.name)
   }
   return o;
 }
 var p1 = person("a");
 var p2 = person("b");
2.构造函数模式创建对象
 function Person(name) {
   this.name = name;
   this.sayName = function() {
     console.log(this.name);
   }
//function() { console.log(this.name);}相当于new Function(){console.log(this.name);}}
 var a = new Person("ww");
 a.sayName();
 console.log(a)

new 一个实例的过程:
(1)先创建一个对象
(2)将构造函数的作用域赋给新对象
(3),执行构造函数中的代码
(4)返回新对象

构造函数模式解决了标识构造函数类型的问题,但是构造函数内部每定义一个函数就会实例化一个对象,可以通过将公用的方法提到全局环境下,通过普通函数调用的方式实现调用函数,避免了重复实例化对象的问题

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

 function sayName() {
   console.log(this.name)
 }
 var a = new Person("p1");
 var b = new Person("p2");
 a.sayName();
 b.sayName();

如果Person内部封装较多的函数,会导致定义大量的全局函数,这些函数散乱分布在全局环境中,失去了封装性.为了解决这个问题,可以用原型模式创建对象

3.原型模式

原型模式创建对象,把属性和函数添加到对象的prototype上,实例化一个对象p1,p1可以通过原型链访问到原型链上的对象

 function Person() {}
 Person.prototype.name = "ww";
 Person.prototype.sayName = function() {
   console.log(this.name);
 }
 var p1 = new Person();
 p1.sayName();

(1)原型模式的另一种方式:

这种方式会导致,Person.prototype上原本指向Person的constructor丢失,可以手动添加constructor属性,如下

(2)如果先创建实例,再定义Person.prototyp的值会报错,p1还是通过[[prototype]]隐式属性指向Person没修改过的原型,导致找不到sayName方法

解释如js高级程序设计一书中的例子:

(3)原型链模式存在以下问题:(1),prototype上的属性和方法共享,一个对象对prototype属性的修改会影响另一个对象的属性;(2)不能传递参数

4.组合使用构造函数和原型函数

我们可以把一些共享的属性和方法添加到prototype,再利用构造函数在实例对象上添加不同属性

二.继承 1.原型链继承

通过将一个构造函数的原型重新赋值(另一个构造函数的实例)实现继承
例子:

function SuperType() {
  this.property = ["p1"];
}
SuperType.prototype.getValue = function() {
  console.log(this.property);
}

function SubType() {
  this.subproperty = ["1"];
}
SubType.prototype.getSubValue = function() {
  console.log("getSubVlue", this.subproperty);
}
SubType.prototype = new SuperType();
var a = new SubType();
console.log("a", a);

结果:

对于引用类型属性,原型链继承会将该属性作为公共属性,谁都可以对它的值进行修改;对于像name这样的非引用类型,每创建一个实例就会定义一个新额属性,不会和其他实例中的属性共享,如下所示

2.借用构造函数

为了解决引用类型值共享的问题和原型链继承不能传递参数的缺陷,可以在子类型构造函数的内部调用超类型构造函数。如下:

function SuperType() {
  this.property = ["p1"];
}
function SubType() {
  this.subproperty = ["1"];
  SuperType.call(this);
}
SubType.prototype = new SuperType();
var a = new SubType();
var b = new SubType();
a.property.push("2");
console.log(a.property, b.property);

利用单纯的借用构造函数解决了引用类型值共享的问题,但是如果大量的函数写着超类中,函数无法复用,所有需要结合原型构造函数.

3.组合构造函数

组合构造函数到的思路是将利用构造函数实例实现对属性的继承,利用原型链来实现对原型对象的属性和函数的继承.

由于给SubType.prototype直接赋值为SuperType的实例,导致constructor丢失,利用Object.defineProperty找回

4.原型式继承

思路:基于已有的对象创建新对象,继承一个现成的对象


原型式继承存在的问题就和原型模式一样,对于引用型属性有共享的特性

5.寄生式继承

思路:创建一个仅用于封装继承过程的函数

该继承方式存在的问题是a对象内部的函数不能复用

6.寄生组合继承

组合构造函数也有缺陷,需要调用两次超类构造函数,降低效率

function SuperType(name) {
  this.name = name;
  this.books = ["b1"]
}

SuperType.prototype.getName = function() {
  console.log(this.name);
}

function SubType(name, age) {
  this.age = age;
  SuperType.call(this, name); //第二次调用构造函数
}

SubType.prototype = new SuperType(); //第一次调用构造函数
SubType.prototype.constructor = SubType;
SubType.prototype.getSubValue = function() {
  console.log("getSubVlue", this.age);
}

利用寄生式继承来继承超类的原型,利用构造函数继承实例属性

有不对或者表达不准确的地方欢迎指出!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102798.html

相关文章

  • 创建对象(一):创建继承

    摘要:创建实例的方式有三种对象字面量表示法操作符跟构造函数中的函数。下面主要讲的是最为复杂的操作符跟构造函数的创建对象实例的方法。 创建对象 一.创建对象的方法 理解原型对象: 无论什么时候,只要创建了新函数,就会根据一组特定的规则为该函数创建一个 prototype属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个constructor属性,这个属性包含一个指向p...

    microelec 评论0 收藏0
  • js继承理解

    摘要:创建自定义的构造函数之后,其原型对象只会取得属性,其他方法都是从继承来的。优缺点寄生式继承在主要考虑对象而不是创建自定义类型和构造函数时,是十分有用的。 原文链接:https://kongchenglc.coding.me... 1.原型链   js的继承机制不同于传统的面向对象语言,采用原型链实现继承,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。理解原型链必须先理...

    BlackFlagBin 评论0 收藏0
  • 《javascript高级程序设计》 继承实现方式

    摘要:寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部已某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象。 这篇本来应该是作为写JS 面向对象的前奏,只是作为《javascript高级程序设计》继承一章的笔记 原型链 code 实现 function SuperType() { this.colors = [red,blu...

    cppprimer 评论0 收藏0
  • JavaScript继承方式详解

    摘要:可以通过构造函数和原型的方式模拟实现类的功能。原型式继承与类式继承类式继承是在子类型构造函数的内部调用超类型的构造函数。寄生式继承这种继承方式是把原型式工厂模式结合起来,目的是为了封装创建的过程。 js继承的概念 js里常用的如下两种继承方式: 原型链继承(对象间的继承) 类式继承(构造函数间的继承) 由于js不像java那样是真正面向对象的语言,js是基于对象的,它没有类的概念。...

    Yangyang 评论0 收藏0
  • 彻底理解Javascript中原型链与继承

    摘要:在节中,我们学习到了通过构造函数创建对象的三个重要步骤,其中的一步是把构造函数的对象设置为创建对象的原型。利用而不是直接用创建一个实例对象的目的是,减少一次调用父构造函数的执行。 JavaScript语言不像面向对象的编程语言中有类的概念,所以也就没有类之间直接的继承,JavaScript中只有对象,使用函数模拟类,基于对象之间的原型链来实现继承关系,ES6的语法中新增了class关键...

    ziwenxie 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<