详解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 相关文章推荐
excel操作之Add Data to a Spreadsheet Cell
Jun 12 Javascript
使用GruntJS构建Web程序之构建篇
Jun 04 Javascript
json属性名为什么要双引号(个人猜测)
Jul 31 Javascript
javascript实现unicode与ASCII相互转换的方法
Dec 10 Javascript
JavaScript判断用户名和密码不能为空的实现代码
May 16 Javascript
Angular5给组件本身的标签添加样式class的方法
Apr 07 Javascript
详解easyui基于 layui.laydate日期扩展组件
Jul 18 Javascript
jQuery仿移动端支付宝键盘的实现代码
Aug 15 jQuery
vue微信分享到朋友圈 vue微信发送给好友
Nov 28 Javascript
vue以组件或者插件的形式实现throttle或者debounce
May 22 Javascript
js实现翻牌小游戏
Jul 31 Javascript
用javascript制作qq注册动态页面
Apr 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
详解WordPress中添加友情链接的方法
2016/05/21 PHP
基于PHP实现数据分页显示功能
2016/05/26 PHP
Yii 框架入口脚本示例分析
2020/05/19 PHP
js实现ASP分页函数 HTML分页函数
2006/09/22 Javascript
在Javascript中为String对象添加trim,ltrim,rtrim方法
2006/09/22 Javascript
js中Math之random,round,ceil,floor的用法总结
2013/12/26 Javascript
jquery动态加载js/css文件方法(自写小函数)
2014/10/11 Javascript
基于JavaScript实现TAB标签效果
2016/01/12 Javascript
Web前端开发工具——bower依赖包管理工具
2016/03/29 Javascript
NodeJS和BootStrap分页效果的实现代码
2016/11/07 NodeJs
JQueryEasyUI之DataGrid数据显示
2016/11/23 Javascript
微信小程序之MaterialDesign--input组件详解
2017/02/15 Javascript
微信小程序分页加载的实例代码
2017/07/11 Javascript
Vue.js 实现数据展示全部和收起功能
2018/09/05 Javascript
zepto.js 实时监听输入框的方法
2018/12/04 Javascript
vue实现鼠标移入移出事件代码实例
2019/03/27 Javascript
JavaScript使用百度ECharts插件绘制饼图操作示例
2019/11/26 Javascript
JS正则表达式验证密码强度
2020/03/18 Javascript
js对象属性名驼峰式转下划线的实例代码
2020/09/17 Javascript
Python批量发送post请求的实现代码
2018/05/05 Python
python-itchat 统计微信群、好友数量,及原始消息数据的实例
2019/02/21 Python
python圣诞树编写实例详解
2020/02/13 Python
为什么相对PHP黑python的更少
2020/06/21 Python
提高python代码运行效率的一些建议
2020/09/29 Python
美国精品家居用品网站:US-Mattress
2016/08/24 全球购物
Bogner美国官网:滑雪服中的”Dior”
2018/01/30 全球购物
英国最大的香水商店:The Fragrance Shop
2018/07/06 全球购物
平面设计师工作职责范文
2013/12/03 职场文书
教育局长自荐信范文
2013/12/22 职场文书
学校党员个人问题整改措施思想汇报
2014/10/08 职场文书
缓刑人员思想汇报
2014/10/11 职场文书
上市公司财务总监岗位职责
2015/04/03 职场文书
2016幼儿园毕业感言
2015/12/08 职场文书
儿童诗两首教学反思
2016/02/23 职场文书
学校团代会开幕词
2016/03/04 职场文书
MySQL中几种插入和批量语句实例详解
2021/09/14 MySQL