详解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中的constructor和prototype
Apr 07 Javascript
jQuery插件jQuery-JSONP开发ajax调用使用注意事项
Nov 22 Javascript
javascript使用定时函数实现跳转到某个页面
Dec 25 Javascript
jquery ajaxSubmit 异步提交的简单实现
Feb 28 Javascript
判断及设置浏览器全屏模式
Apr 20 Javascript
javascript垃圾收集机制的原理分析
Dec 08 Javascript
详解jQuery中的isPlainObject()使用方法
Feb 27 jQuery
Vue 递归多级菜单的实例代码
May 05 Javascript
了解javascript中的Dom操作
May 27 Javascript
layui加载表格,绑定新增,编辑删除,查看按钮事件的例子
Sep 06 Javascript
浅析我对JS延迟异步脚本的思考
Oct 12 Javascript
JavaScript大数相加相乘的实现方法实例
Oct 18 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简单实现文本计数器的方法
2016/04/28 PHP
form表单传递数组数据、php脚本接收的实例
2017/02/09 PHP
cakephp2.X多表联合查询join及使用分页查询的方法
2017/02/23 PHP
laravel框架中路由设置,路由参数和路由命名实例分析
2019/11/23 PHP
JavaScript 类似flash效果的立体图片浏览器
2010/02/08 Javascript
Javascript模块化编程(一)模块的写法最佳实践
2013/01/17 Javascript
父页面显示遮罩层弹出半透明状态的dialog
2014/03/04 Javascript
ext combobox动态加载数据库数据(附前后台)
2014/06/17 Javascript
Javascript实现检测客户端类型代码封包
2015/12/03 Javascript
基于jQuery.validate及Bootstrap的tooltip开发气泡样式的表单校验组件思路详解
2016/07/18 Javascript
详解Html a标签中href和onclick用法、区别、优先级别
2017/01/16 Javascript
JS文件/图片从电脑里面拖拽到浏览器上传文件/图片
2017/03/08 Javascript
基于jQuery和CSS3实现APPLE TV海报视差效果
2017/06/16 jQuery
详解webpack编译多页面vue项目的配置问题
2017/12/11 Javascript
微信小程序实现全国机场索引列表
2018/01/31 Javascript
JS实现可用滑块滑动的缓动图代码
2019/09/01 Javascript
vue实现element表格里表头信息提示功能(推荐)
2019/11/20 Javascript
toString.call()通用的判断数据类型方法示例
2020/08/28 Javascript
python操作ie登陆土豆网的方法
2015/05/09 Python
Python打包可执行文件的方法详解
2016/09/19 Python
Python3.4实现从HTTP代理网站批量获取代理并筛选的方法示例
2017/09/26 Python
Python探索之SocketServer详解
2017/10/28 Python
Pandas 同元素多列去重的实例
2018/07/03 Python
python如何实现从视频中提取每秒图片
2020/10/22 Python
python创建学生成绩管理系统
2019/11/22 Python
python 监测内存和cpu的使用率实例
2019/11/28 Python
Python3常见函数range()用法详解
2019/12/30 Python
python PIL/cv2/base64相互转换实例
2020/01/09 Python
如何把外网python虚拟环境迁移到内网
2020/05/18 Python
python try...finally...的实现方法
2020/11/25 Python
详解CSS的border边框属性及其在CSS3中的新特性
2016/05/10 HTML / CSS
失业者真诚求职信范文
2013/12/25 职场文书
六查六看剖析材料
2014/10/06 职场文书
Python爬虫基础之爬虫的分类知识总结
2021/05/13 Python
MySQL七种JOIN类型小结
2021/10/24 MySQL
win10如何开启ahci模式?win10开启ahci模式详细操作教程
2022/07/23 数码科技