详解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 相关文章推荐
点击文章内容处弹出页面代码
Oct 01 Javascript
深入理解JavaScript系列(7) S.O.L.I.D五大原则之开闭原则OCP
Jan 15 Javascript
js调用后台servlet方法实例
Jun 09 Javascript
jquery实现的导航固定效果
Apr 28 Javascript
JavaScript中的值是按值传递还是按引用传递问题探讨
Jan 30 Javascript
zepto中使用swipe.js制作轮播图附swipeUp,swipeDown不起效果问题
Aug 27 Javascript
JavaScript仿支付宝密码输入框
Dec 29 Javascript
jQuery删除节点用法示例(remove方法)
Sep 08 Javascript
Javascript 实现计算器时间功能详解及实例(二)
Jan 08 Javascript
Vue 实现树形视图数据功能
May 07 Javascript
vue-devtools的安装和使用步骤详解
Oct 17 Javascript
vue3不同环境下实现配置代理
May 25 Vue.js
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 FLEA中二叉树数组的遍历输出
2012/09/26 PHP
php抓取并保存网站图片的实现代码
2015/10/28 PHP
php利用嵌套数组拼接与解析json的方法
2017/02/07 PHP
PHP实现的支付宝支付功能示例
2019/03/26 PHP
PHP检查文件是否存在,不存在自动创建及读取文件内容操作示例
2020/01/23 PHP
从父页面读取和操作iframe中内容方法
2009/07/25 Javascript
基于jQuery的日期选择控件
2009/10/27 Javascript
关于JavaScript定义类和对象的几种方式
2010/11/09 Javascript
js获取网页高度(详细整理)
2012/12/28 Javascript
js遍历、动态的添加数据的小例子
2013/06/22 Javascript
基于JS实现简单的样式切换效果代码
2015/09/04 Javascript
jquery实现删除一个元素后面的所有元素功能
2015/12/21 Javascript
详解vue.js组件化开发实践
2016/12/14 Javascript
通过AngularJS实现图片上传及缩略图展示示例
2017/01/03 Javascript
JS身份证信息验证正则表达式
2017/06/12 Javascript
微信小程序的生命周期的详解
2017/10/19 Javascript
Element-ui之ElScrollBar组件滚动条的使用方法
2018/09/14 Javascript
Jquery cookie插件实现原理代码解析
2020/08/04 jQuery
Vue2.0 ES6语法降级ES5的操作
2020/10/30 Javascript
在Python中使用itertools模块中的组合函数的教程
2015/04/13 Python
Python科学计算包numpy用法实例详解
2018/02/08 Python
Python针对给定字符串求解所有子序列是否为回文序列的方法
2018/04/21 Python
python 返回列表中某个值的索引方法
2018/11/07 Python
Python使用pandas对数据进行差分运算的方法
2018/12/22 Python
python腾讯语音合成实现过程解析
2019/08/01 Python
详解python对象之间的交互
2020/09/29 Python
python3爬虫中多线程进行解锁操作实例
2020/11/25 Python
如何用 Python 处理不平衡数据集
2021/01/04 Python
智能电子秤、手表和健康监测仪:Withings(之前为诺基亚健康)
2018/10/30 全球购物
Kipling澳洲官网:购买凯浦林包包
2020/12/17 全球购物
实习教师自我鉴定
2013/12/12 职场文书
名企HR怎样看待求职信
2014/02/23 职场文书
2014年话务员工作总结
2014/11/19 职场文书
详解Vue的sync修饰符
2021/05/15 Vue.js
Python编写冷笑话生成器
2022/04/20 Python
win10忘记pin密码登录不了怎么办?win10忘记pin密码登不进去的解决方法
2022/07/07 数码科技