详解JavaScript中基于原型prototype的继承特性


Posted in Javascript onMay 05, 2016

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
Javascript 相关文章推荐
js使用ajax读博客rss示例
May 06 Javascript
jquery使用经验小结
May 20 Javascript
JavaScript中的return语句简单介绍
Dec 07 Javascript
基于Javascript实现弹出页面效果
Jan 01 Javascript
详解Node.js模块间共享数据库连接的方法
May 24 Javascript
JS获取checkbox的个数简单实例
Aug 19 Javascript
React Native实现简单的登录功能(推荐)
Sep 19 Javascript
JavaScript中日常收集常见的10种错误(推荐)
Jan 08 Javascript
javascript 组合按键事件监听实现代码
Feb 21 Javascript
Vue渲染函数详解
Sep 15 Javascript
jQuery实现鼠标响应式淘宝动画效果示例
Feb 13 jQuery
浅谈PDF.js使用心得
Jun 07 Javascript
5个最顶级jQuery图表类库插件【jquery插件库】
May 05 #Javascript
javaScript中的原型解析【推荐】
May 05 #Javascript
实例讲解JavaScript的Backbone.js框架中的View视图
May 05 #Javascript
全面解析JavaScript的Backbone.js框架中的Router路由
May 05 #Javascript
详解Backbone.js框架中的模型Model与其集合collection
May 05 #Javascript
基于jQuery实现动态搜索显示功能
May 05 #Javascript
jQuery插件ajaxfileupload.js实现上传文件
Oct 23 #Javascript
You might like
自定义session存储机制避免会话保持问题
2014/10/08 PHP
Thinkphp 框架配置操作之配置加载与读取配置实例分析
2020/05/15 PHP
javascript 同时在IE和FireFox获取KeyCode的代码
2010/02/07 Javascript
javascript延时加载之defer测试
2012/12/28 Javascript
js自动下载文件到本地的实现代码
2013/04/28 Javascript
Extjs Label的 fieldLabel和html属性值对齐的方法
2014/06/15 Javascript
jQuery中data()方法用法实例
2014/12/27 Javascript
PHP+jQuery实现随意拖动层并即时保存拖动位置
2015/04/30 Javascript
JS折半插入排序算法实例
2015/12/02 Javascript
jquery弹出遮掩层效果【附实例代码】
2016/04/28 Javascript
基于javascript实现图片滑动效果
2016/05/07 Javascript
require简单实现单页应用程序(SPA)
2016/07/12 Javascript
纯JavaScript手写图片轮播代码
2016/10/20 Javascript
AngularJS入门教程之Cookies读写操作示例
2016/11/02 Javascript
Angularjs中的页面访问权限怎么设置
2016/11/11 Javascript
浅谈Angular的$q, defer, promise
2016/12/20 Javascript
vue的for循环使用方法
2019/02/12 Javascript
vue cli3.0 引入eslint 结合vscode使用
2019/05/27 Javascript
python实现的生成随机迷宫算法核心代码分享(含游戏完整代码)
2014/07/11 Python
在Mac OS上搭建Python的开发环境
2015/12/24 Python
Python面向对象class类属性及子类用法分析
2018/02/02 Python
值得收藏,Python 开发中的高级技巧
2018/11/23 Python
python字符串循环左移
2019/03/08 Python
Python之Class&Object用法详解
2019/12/25 Python
非常震撼的纯CSS3人物行走动画
2016/02/24 HTML / CSS
英国信箱在线鲜花速递公司:Bloom & Wild
2019/03/10 全球购物
python+selenium小米商城红米K40手机自动抢购的示例代码
2021/03/24 Python
大专生自我鉴定范文
2013/10/01 职场文书
共产党员承诺书
2014/03/25 职场文书
党的群众路线对照检查材料思想汇报(学校)
2014/10/04 职场文书
党员带头倡议书
2015/04/29 职场文书
走进毛泽东观后感
2015/06/04 职场文书
励志语录:只有自己足够强大,才能不被别人践踏
2020/01/09 职场文书
用Python简陋模拟n阶魔方
2021/04/17 Python
vue项目中的支付功能实现(微信支付和支付宝支付)
2022/02/18 Vue.js
python如何查找列表中元素的位置
2022/05/30 Python