详解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 冒号 使用说明
Jun 06 Javascript
JavaScript判断变量是否为undefined的两种写法区别
Dec 04 Javascript
AngularJS基础 ng-dblclick 指令用法
Aug 01 Javascript
JS文件/图片从电脑里面拖拽到浏览器上传文件/图片
Mar 08 Javascript
Vue 2.0在IE11中打开项目页面空白的问题解决
Jul 16 Javascript
Vue学习笔记进阶篇之函数化组件解析
Jul 21 Javascript
jQuery条件分页 代替离线查询(附代码)
Aug 17 jQuery
使用react-router4.0实现重定向和404功能的方法
Aug 28 Javascript
JS获取当前地理位置的方法
Oct 25 Javascript
vue利用v-for嵌套输出多层对象,分别输出到个表的方法
Sep 07 Javascript
如何在node环境实现“get数据解析”代码实例
Jul 03 Javascript
Vue实现菜单切换功能
Nov 08 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
CI框架开发新浪微博登录接口源码完整版
2014/05/28 PHP
php+ajax实现文章自动保存的方法
2014/12/30 PHP
jquery append()方法与html()方法的区别及使用介绍
2014/08/01 Javascript
Node.js的特点和应用场景介绍
2014/11/04 Javascript
JavaScript中发布/订阅模式的简单实例
2014/11/05 Javascript
js实现的全国省市二级联动下拉选择菜单完整实例
2015/08/17 Javascript
JavaScript的removeChild()函数用法详解
2015/12/27 Javascript
javascript对象的创建和访问
2016/03/08 Javascript
通过bootstrap全面学习less
2016/11/09 Javascript
完美的js图片轮换效果
2017/02/05 Javascript
jQuery实现web页面樱花坠落的特效
2017/06/01 jQuery
详解Vue 方法与事件处理器
2017/06/20 Javascript
使用Webpack提高Vue.js应用的方式汇总(四种)
2017/07/10 Javascript
js图片放大镜实例讲解(必看篇)
2017/07/17 Javascript
iscroll实现下拉刷新功能
2017/07/18 Javascript
vue2.x+webpack快速搭建前端项目框架详解
2017/11/30 Javascript
基于Vue实现微信小程序的图文编辑器
2018/07/25 Javascript
2019最新21个MySQL高频面试题介绍
2020/02/06 Javascript
解决vuex改变了state的值,但是页面没有更新的问题
2020/11/12 Javascript
Python中模拟enum枚举类型的5种方法分享
2014/11/22 Python
Python中类型关系和继承关系实例详解
2015/05/25 Python
python类装饰器用法实例
2015/06/04 Python
Python中的上下文管理器和with语句的使用
2018/04/17 Python
Python获取、格式化当前时间日期的方法
2020/02/10 Python
python实现图像全景拼接
2020/03/27 Python
python手机号前7位归属地爬虫代码实例
2020/03/31 Python
python使用自定义钉钉机器人的示例代码
2020/06/24 Python
Python 解析xml文件的示例
2020/09/29 Python
html5中localStorage本地存储的简单使用
2017/06/16 HTML / CSS
亚马逊墨西哥站:Amazon.com.mx
2018/08/26 全球购物
荷兰照明、灯具和配件网上商店:dmlights
2019/08/25 全球购物
工作中的自我评价如何写好
2013/10/28 职场文书
文明礼仪标语
2014/06/13 职场文书
小学生禁毒教育心得体会
2016/01/15 职场文书
为什么 Nginx 比 Apache 更牛逼
2021/03/31 Servers
Python集合set()使用的方法详解
2022/03/18 Python