详解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 相关文章推荐
通用javascript脚本函数库 方便开发
Oct 13 Javascript
jQuery EasyUI 中文API Button使用实例
Apr 14 Javascript
javascript中的变量是传值还是传址的?
Apr 19 Javascript
鼠标悬浮停留三秒后自动显示大图js代码
Sep 09 Javascript
JS操作XML实例总结(加载与解析XML文件、字符串)
Dec 08 Javascript
js插件Jcrop自定义截取图片功能
Oct 14 Javascript
javascript获取以及设置光标位置
Feb 16 Javascript
Javascript中从学习bind到实现bind的过程
Jan 05 Javascript
Easyui 关闭jquery-easui tab标签页前触发事件的解决方法
Apr 28 jQuery
vue + typescript + 极验登录验证的实现方法
Jun 27 Javascript
通过实例了解Javascript柯里化流程
Mar 03 Javascript
js实现自定义滚动条的示例
Oct 27 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
浅析php创建者模式
2014/11/25 PHP
php swoole多进程/多线程用法示例【基于php7nts版】
2019/08/12 PHP
指定js可访问其它域名的cookie的方法
2007/09/18 Javascript
JS 分号引起的一段调试问题
2009/06/18 Javascript
基于jQuery的试卷自动排版系统实现代码
2011/01/06 Javascript
深入理解javascript学习笔记(一) 编写高质量代码
2012/08/09 Javascript
javascript中的原型链深入理解
2014/02/24 Javascript
举例详解AngularJS中ngShow和ngHide的使用方法
2015/06/19 Javascript
Javascript模仿淘宝信用评价实例(附源码)
2015/11/26 Javascript
JS获取鼠标相对位置的方法
2016/09/20 Javascript
Easyui的组合框的取值与赋值
2016/10/28 Javascript
vue.js 获取当前自定义属性值
2017/06/01 Javascript
vue计算属性和监听器实例解析
2018/05/10 Javascript
vue指令做滚动加载和监听等
2019/05/26 Javascript
解决Vue的项目使用Element ui 走马灯无法实现的问题
2020/08/03 Javascript
vue-calendar-component 封装多日期选择组件的实例代码
2020/12/04 Vue.js
[02:07]DOTA2超级联赛专访BBC:难忘网吧超神经历
2013/06/09 DOTA
python读写ini文件示例(python读写文件)
2014/03/25 Python
Python进程通信之匿名管道实例讲解
2015/04/11 Python
Python3实现的简单三级菜单功能示例
2019/03/12 Python
Python Pandas分组聚合的实现方法
2019/07/02 Python
python如何实现从视频中提取每秒图片
2020/10/22 Python
python协程gevent案例 爬取斗鱼图片过程解析
2019/08/27 Python
浅谈TensorFlow之稀疏张量表示
2020/06/30 Python
html5写一个BUI折叠菜单插件的实现方法
2019/09/11 HTML / CSS
Cotton On香港网站:澳洲时装连锁品牌
2018/11/01 全球购物
精彩的大学生自我评价
2013/11/17 职场文书
家长对老师的评语
2014/04/18 职场文书
好学生评语大全
2014/05/05 职场文书
审计局2014法制宣传日活动总结
2014/11/01 职场文书
小学生作文批改评语
2014/12/25 职场文书
建党伟业电影观后感
2015/06/01 职场文书
《莫泊桑拜师》教学反思
2016/02/22 职场文书
基于Go Int转string几种方式性能测试
2021/04/28 Golang
go使用Gin框架利用阿里云实现短信验证码功能
2021/08/04 Golang
JavaScript模拟实现网易云轮播效果
2022/04/04 Javascript