详解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 相关文章推荐
Web层改进II-用xmlhttp 无声息提交复杂表单
Jan 22 Javascript
在多个页面使用同一个HTML片段《续》
Mar 04 Javascript
幻灯片带网页设计中的20个奇妙应用示例小结
May 27 Javascript
js获得鼠标的坐标值的方法
Mar 13 Javascript
简洁Ajax函数处理(示例代码)
Nov 15 Javascript
Internet Explorer 11 浏览器介绍:别叫我IE
Sep 28 Javascript
JS右下角广告窗口代码(可收缩、展开及关闭)
Sep 04 Javascript
Node.js编写组件的三种实现方式
Feb 25 Javascript
AngularJS 输入验证详解及实例代码
Jul 28 Javascript
Node.js检测端口(port)是否被占用的简单示例
Sep 29 Javascript
koa大型web项目中使用路由装饰器的方法示例
Apr 02 Javascript
解决vue中使用proxy配置不同端口和ip接口问题
Aug 14 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
关于PHPDocument 代码注释规范的总结
2013/06/25 PHP
PHP正则替换函数preg_replace和preg_replace_callback使用总结
2014/09/22 PHP
用javascript来实现动画导航效果的代码
2007/12/16 Javascript
Prototype Number对象 学习
2009/07/19 Javascript
用nodejs写的一个简单项目打包工具
2013/05/11 NodeJs
使用非html5实现js板连连看游戏示例代码
2013/09/22 Javascript
JS获取地址栏参数的几种方法小结
2014/02/28 Javascript
jQuery实现鼠标经过图片预览大图效果
2014/04/10 Javascript
jQuery焦点图轮播特效代码分享(3款)
2015/09/05 Javascript
基于javascript实现图片左右切换效果
2016/01/25 Javascript
Nodejs下用submit提交表单提示cannot post错误的解决方法
2016/11/21 NodeJs
React.js中常用的ES6写法总结(推荐)
2017/05/09 Javascript
用vue封装插件并发布到npm的方法步骤
2017/10/18 Javascript
React Native使用fetch实现图片上传的示例代码
2018/03/07 Javascript
JS实现贪吃蛇游戏
2019/11/15 Javascript
Django接受前端数据的几种方法总结
2016/11/04 Python
详解Python多线程
2016/11/14 Python
使用python实现tcp自动重连
2017/07/02 Python
python自动登录12306并自动点击验证码完成登录的实现源代码
2018/04/25 Python
基于Python List的赋值方法
2018/06/23 Python
在Mac上删除自己安装的Python方法
2018/10/29 Python
Django实现文件上传和下载功能
2019/10/06 Python
pytorch 获取tensor维度信息示例
2020/01/03 Python
pycharm安装及如何导入numpy
2020/04/03 Python
导致python中import错误的原因是什么
2020/07/01 Python
Pycharm2020.1安装中文语言插件的详细教程(不需要汉化)
2020/08/07 Python
Html5 APP中监听返回事件处理的方法示例
2018/03/15 HTML / CSS
客户接待方案
2014/02/26 职场文书
新春联欢会主持词
2014/03/24 职场文书
企业承诺书怎么写
2014/05/24 职场文书
关于安全的标语
2014/06/10 职场文书
2014工程部年度工作总结
2014/12/17 职场文书
2015年入党积极分子评语
2015/03/26 职场文书
六年级语文教学反思
2016/03/03 职场文书
某某店铺的开业庆典主持词范本
2019/11/25 职场文书
ubuntu20.04虚拟机无法上网的问题及解决
2022/12/24 Servers