javascript创建对象、对象继承的实用方式详解


Posted in Javascript onMarch 08, 2016

本文约定:不特殊声明的情况下,属性代指属性或方法。

创建对象、对象继承实际上是一回事:我们所需要的实例对象通过构造函数获得私有属性、通过原型链获得共享的属性。什么是好的方式?私有属性通过构造函数的方式获得(不考虑实例中自定义私有属性)且不需要重写,共享属性通过原型链找到且不需要重复创建。

普适的方式

组合使用构造函数模式和原型模式创建对象

function HNU_student(name) {
  this.name = name;
  this.sayName = function() {
    return this.name;
  };
}
HNU_student.prototype = {
  school: 'HNU',
  saySchool: function() {
    return this.school;
  }
};
Object.defineProperty(HNU_student, 'constructor', {value: HNU_student});

var hiyohoo = new HNU_student('xujian');

通过字面量的方式会重写prototype,且原型的constructor指向了Object,必要的情况下需要重新定义constructor。

寄生组合式继承

function object(o) {
  function F() {};
  F.prototype = o;
  return new F();
}
function inheritPrototype(child, parent) {
  var prototype = object(parent.prototype);
  prototype.constructor = child;
  child.prototype = prototype;
}

function HNU_student(name) {
  this.name = name;
  this.sayName = function() {
    return this.name;
  };
}
HNU_student.prototype.school = 'HNU';
HNU_student.prototype.saySchool = function() {
  return this.school;
};

function Student_2011(name, number) {
  HNU_student.call(this, name);
  this.number = number;
  this.sayNumber = function() {
    return this.number;
  }
}
inheritPrototype(Student_2011, HNU_student);
Student_2011.prototype.graduationTime = 2015;
Student_2011.prototype.sayGraduationTime = function() {
  return this.graduationTime;
};

var hiyohoo = new Student_2011('xujian', 20110803203);

object()的作用:将作为参数传入的对象变成实例的原型,该对象的属性被所有实例共享。

共享属性:inheritPrototype(Student_2011, HNU_student);,子构造函数原型成为超构造函数原型的一个实例,超构造函数原型中的属性共享给子构造函数。
私有属性:HNU_student.call(this, name);,通过子构造函数创建实例时调用超构造函数创建私有属性。

创建对象的其他方式

动态原型模式

function HNU_student(name) {
  this.name = name;
  this.sayName = function() {
    return this.name;
  };

  if (!HNU_student.prototype.school) {
    HNU_student.prototype.school = 'HNU';
    HNU_student.prototype.saySchool = function() {
      return this.school;
    };
  }
}

var hiyohoo = new HNU_student('xujian');

将定义在原型中的共享属性放入构造函数中,使用判断语句,在第一次调用构造函数创建实例时,初始化原型共享属性。

寄生构造函数模式

function SpecialArray() {
  var values = new Array();
  values.push.apply(values, arguments);
  values.toPipedString = function() {
    return this.join('|');
  };

  return values;
}

var colors = new SpecialArray('red', 'black', 'white');

用于为原生构造函数添加特殊的属性。

对象继承的其他方式

组合继承

function HNU_student(name) {
  this.name = name;
  this.sayName = function() {
    return this.name;
  };
}
HNU_student.prototype.school = 'HNU';
HNU_student.prototype.saySchool = function() {
  return this.school;
};
function Student_2011(name, number) {
  HNU_student.call(this, name);
  this.number = number;
  this.sayNumber = function() {
    return this.number;
  };
}
Student_2011.prototype = new HNU_student();
Student_2011.prototype.constructor = Student_2011;
Student_2011.prototype.graduationTime = 2015;
Student_2011.prototype.sayGraduationTime = function() {
  return this.graduationTime;
}
var hiyohoo = new Student_2011('xujian', 20110803203);

共享属性:Student_2011.prototype = new HNU_student();,子构造函数的原型就指向了超构造函数的原型,实例通过原型链找到所有共享的属性。
私有属性:HNU_student.call(this, name);,通过子构造函数创建实例时调用超构造函数创建私有属性。

缺陷:超构造函数被调用了两遍。Student_2011.prototype = new HNU_student();的同时,在子构造函数原型中创建了超构造函数定义的私有属性,这些原型中的私有属性被实例中的同名属性覆盖屏蔽。

原型式继承、寄生式继承

function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}
var student1 = {
  school: 'HNU',
  saySchool: function() {
    return this.school;
  }
};
var student2 = object(student1);

Object.creat()是ECMAScript5新增的方法,接受两个参数:一是作为原型的原对象,二是重写或新增属性的对象,作用与自定义的object()相同。

var student1 = {
  name: 'xujian',
  school: 'HNU'
};
var student2 = Object.create(student1, {
  name: {
    value: 'huangjing'
  }
});

寄生式继承在原型式继承的基础上添加了额外的属性用来增强对象。

function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}
function creatAnother(original) {
  var clone = object(original);
  clone.sayHi = function() {
    alert('Hi!');
  };
  return clone;
}
var student1 = {
  school: 'HNU',
  saySchool: function() {
    return this.school;
  }
};
var student2 = creatAnother(student1);

原型式继承和寄生式继承用于创建与已有对象类似的实例对象。

Javascript 相关文章推荐
从零开始学习jQuery (八) 插播:jQuery实施方案
Feb 23 Javascript
基于jquery的设置页面文本框 只能输入数字的实现代码
Apr 19 Javascript
获取表单控件原始(初始)值的方法
Aug 21 Javascript
两个select多选模式的选项相互移动(示例代码)
Jan 11 Javascript
javascript常见操作汇总
Sep 03 Javascript
解析javascript中鼠标滚轮事件
May 26 Javascript
JS代码实现根据时间变换页面背景效果
Jun 16 Javascript
利用python分析access日志的方法
Oct 26 Javascript
VUE-cli3使用 svg-sprite-loader
Oct 20 Javascript
angularjs http与后台交互的实现示例
Dec 21 Javascript
如何在vue里面优雅的解决跨域(路由冲突问题)
Jan 20 Javascript
VUE注册全局组件和局部组件过程解析
Oct 10 Javascript
理解javascript正则表达式
Mar 08 #Javascript
JavaScript实现带播放列表的音乐播放器实例分享
Mar 07 #Javascript
详解JavaScript数组和字符串中去除重复值的方法
Mar 07 #Javascript
JavaScript实现字符串与日期的互相转换及日期的格式化
Mar 07 #Javascript
JavaScript中将数组进行合并的基本方法讲解
Mar 07 #Javascript
Bootstrap每天必学之日期控制
Mar 07 #Javascript
JavaScript过滤字符串中的中文与空格方法汇总
Mar 07 #Javascript
You might like
关于php curl获取301或302转向的网址问题的解决方法
2011/06/02 PHP
ThinkPHP实现跨模块调用操作方法概述
2014/06/20 PHP
PHP的时间戳与具体时间转化的简单实现
2016/06/13 PHP
JSON为什么那样红为什么要用json(另有洞天)
2012/12/26 Javascript
Js中setTimeout()和setInterval() 何时被调用执行的用法
2013/04/12 Javascript
javascript不可用的问题探究
2013/10/01 Javascript
JS仿百度搜索自动提示框匹配查询功能
2013/11/21 Javascript
JavaScript判断图片是否已经加载完毕的方法汇总
2016/02/05 Javascript
jQuery插件EasyUI实现Layout框架页面中弹出窗体到最顶层效果(穿越iframe)
2016/08/05 Javascript
javascript replace()第二个参数为函数时的参数用法
2016/12/26 Javascript
Javascript基础回顾之(三) js面向对象
2017/01/31 Javascript
微信小程序 PHP生成带参数二维码
2017/02/21 Javascript
收藏AngularJS中最重要的核心功能
2017/07/09 Javascript
利用纯JS实现像素逐渐显示的方法示例
2017/08/14 Javascript
ES6 javascript的异步操作实例详解
2017/10/30 Javascript
详解node Async/Await 更好的异步编程解决方案
2018/05/10 Javascript
vue表单自定义校验规则介绍
2018/08/28 Javascript
Vue中的组件及路由使用实例代码详解
2019/05/22 Javascript
js实现弹幕飞机效果
2020/08/27 Javascript
Python pickle模块用法实例分析
2015/05/27 Python
Python编程中装饰器的使用示例解析
2016/06/20 Python
python实现BP神经网络回归预测模型
2019/08/09 Python
python打印直角三角形与等腰三角形实例代码
2019/10/20 Python
CSS3中border-radius属性设定圆角的使用技巧
2016/05/10 HTML / CSS
利用Bootstrap实现漂亮简洁的CSS3价格表实例源码
2017/03/02 HTML / CSS
纯CSS3实现的井字棋游戏
2020/11/25 HTML / CSS
H5仿微信界面教程(一)
2017/07/05 HTML / CSS
Canvas制作的下雨动画的示例
2018/03/06 HTML / CSS
药剂学专业应届生自荐信
2013/09/29 职场文书
《水上飞机》教学反思
2014/04/10 职场文书
python使用glob检索文件的操作
2021/05/20 Python
MySQL查看表和清空表的常用命令总结
2021/05/26 MySQL
教你用Python爬取英雄联盟皮肤原画
2021/06/13 Python
解决Mysql多行子查询的使用及空值问题
2022/01/22 MySQL
MySql分区类型及创建分区的方法
2022/04/13 MySQL
插件导致ECharts被全量引入的坑示例解析
2022/09/23 Javascript