详解JavaScript中基于原型prototype的继承特性
来源: 阅读:742 次 日期:2016-07-02 14:05:14
温馨提示: 小编为您整理了“详解JavaScript中基于原型prototype的继承特性”,方便广大网友查阅!

这篇文章主要介绍了详解JavaScript中基于原型prototype的继承特性,JavaScript中缺少类等面向对象的重要特性,因而谈到继承也显得十分古怪...需要的朋友可以参考下

JavaScript 中的继承比较奇葩,无法实现接口继承,只能依靠原型继承。

原型链

原型就是一个对象,通过构造函数创建出来的实例会有指针指向原型得到原型的属性和方法。这样,实例对象就带有构造函数的属性方法和原型的属性方法,然后将需要继承的构造函数的原型指向这个实例,即可拥有这个实例的所有属性方法实现继承。

看下面演示代码:

//声明超类,通过构造函数和原型添加有关属性和方法

function Super(){

  this.property = true;

}

Super.prototype.getSuperValue = function() {

  return this.property;

};

//声明子类的构造函数

function SubType() {

  this.subproperty = false;

}

//将子类的原型指向超类的实例,得到超类的一切

SubType.prototype = new Super();

SubType.prototype.constructor = SubType;

SubType.prototype.getSubValue = function(){

  return this.subproperty;

};

//由子类创建对象,测试是否继承超类方法和属性

var instance = new SubType();

console.log(instance.getSuperValue());

所有函数的默认原型都是 Object 的实例,因此默认原型都会包含一个内部指针,指向 Object.prototype。

使用 instanceof 和 isPrototypeOf 可以确定原型和实例的关系:

instance instanceof Object;

Object.prototype.isPrototypeOf(instance);

使用原型链的时候,需要谨慎的定义方法。子类需要重写超类型的某个方法或者扩充,一定要放在替换原型的语句后面,这样才能生效。此外,通过原型链实现继承时,不能使用对象字面量创建原型方法,这样会重写原型链:

......

SubType.prototype = new Super();

SubType.prototype = {

  ....

};

这会更换指针指向新对象,从而重写了原型链。

原型链的继承方法是有缺陷的,主要有两个问题:

1,来自包含引用类型值的原型,会被所有实例共享。

前面文章介绍过包含引用类型值的原型属性会被所有实例共享,一个实例修改,其他实例会随之改变,因此需要在构造函数中定义属性。而原型链继承的时候,无论超类中属性是在构造函数还是原型中定义,全部都变成了实例对象被子类继承,从而对子类的实例产生影响。

2,创建子类型的实例时,不能向超类型的构造函数中传递参数。

原型链的继承,直接将子类原型指向超类的实例,这时候可以向超类传递参数。但是当子类创建实例的时候,只能向子类的构造函数传递参数,而不能向超类的构造函数传递参数。

因此实际应用中,很少单独使用原型链。

相关的一些代码实践

鉴别一个原型属性

function hasPrototypeProperty(object, name) {

  return name in object && !object.hasOwnProperty(name);

}

在构造函数中使用原型对象

function Person(name) {

  this.name = name;

}

Person.prototype = {

  constructor: Person,

  sayName: function () {

    console.log(this.name);

  },

  toString: function() {

  }

};

var person1 = new Person('Nicholas');

var person2 = new Person('Greg);

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

console.log(person1.constructor === Person); // true

console.log(person1.constructor === Object); // false

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

console.log(person2.constructor === Person); // true

console.log(person2.constructor === Object); // false

对象继承

var person1 = {

  name: 'Nicholas',

  sayName: function () {

    console.log(this.name);

  }

};

var person2 = Object.create(person1, {

  name: {

    configurable: true,

    enumerable: true,

    value: 'Greg',

    writable: true

  }

});

person1.sayName(); // Nicholas

person2.sayName(); // Greg

console.log(person1.hasOwnProperty('sayName')); // true

console.log(person1.isPropertyOf(person2)); // true

console.log(person2.hasOwnProperty('sayName')); // false

模块模式

var person = (function () {

  var age = 25;

  function getAge() {

    return age;

  }

  function growOlder() {

    age++;

  }

  return {

    name: 'Nicholas',

    getAge: getAge,

    growOlder: growOlder

  };

}());

作用域的构造函数

function Person(name) {

  this.name = name;

}

Person.prototype.sayName = function() {

  console.log(this.name);

};

var person1 = Person('Nicholas');

console.log(person1 instanceof Person); // false

console.log(typeof person1); // undefined

console.log(name); // Nicholas

更多信息请查看网络编程
由于各方面情况的不断调整与变化, 提供的所有考试信息和咨询回复仅供参考,敬请考生以权威部门公布的正式信息和咨询为准!
关于我们 | 联系我们 | 人才招聘 | 网站声明 | 网站帮助 | 非正式的简要咨询 | 简要咨询须知 | 加入群交流 | 手机站点 | 投诉建议
工业和信息化部备案号:滇ICP备2023014141号-1 云南省教育厅备案号:云教ICP备0901021 滇公网安备53010202001879号 人力资源服务许可证:(云)人服证字(2023)第0102001523号
云南网警备案专用图标
联系电话:0871-65317125(9:00—18:00) 获取招聘考试信息及咨询关注公众号:hfpxwx
咨询QQ:526150442(9:00—18:00)版权所有:
云南网警报警专用图标
Baidu
map