js 面向对象 继承机制
根据w3cschool上的描述:共有3种继承方法(对象冒充,原型链,混合)
1、对象冒充:构造函数ClassA使用this关键字给所有属性和方法赋值,使ClassA构造函数成为ClassB的方法,调用。可实现多重继承。
注意:所有新属性和新方法都必须在删除新方法的代码行后定义,否则会覆盖父类的相关属性和方法,多重继承时存在同名问题。
原始:
function ClassA(sColor){
this.color = sColor
this.sayColor = function(){
alert(this.color);
};
};
function ClassB(sColor, sName){
this.newMethod = ClassA;
this.newMethod(sColor);
delete this.newMethod;
//新属性和方法
this.name = sName;
this.sayName = function(){
alert(this.name);
}
}
var objA = new ClassA('blue');
var objB = new ClassB('red', 'jack');
call():function对象的一个方法,它是ECMASript把对象冒充规范化的结果
function ClassB(sColor, sName) {
//this.newMethod = ClassA;
//this.newMethod(color);
//delete this.newMethod;
ClassA.call(this, sColor);
this.name = sName;
this.sayName = function () {
alert(this.name);
};
}
apple():与call类似,第二个参数是数组或arguments(参数对象,两个类中的参数顺序完全一致的话,才可以)
function ClassB(sColor, sName) {
//this.newMethod = ClassA;
//this.newMethod(color);
//delete this.newMethod;
ClassA.apply(this, new Array(sColor));
this.name = sName;
this.sayName = function () {
alert(this.name);
};
}
以上存在内存浪费的问题。那就是对于每个实例对象而言,属性和方法都是一样的,但是每次创建新的实例,都要为其分配新的内存空间,这样做就会降低性能,浪费空间,缺乏效率。
2、原型链:把ClassB的prototype属性设置成ClassA的实例。ClassA的构造函数不能传递参数。
注意:所有新属性和新方法都必须在删除新方法的代码行后定义,否则会覆盖父类的相关属性和方法:因为prototype属性被替换成了新对象,添加了新方法和属性的原始对象将被销毁。
对 ClassB 的所有实例,instanceof 为 ClassA 和 ClassB 都返回 true。对象冒充时不能这样(instanceof是讲类型的,而对象冒充是讲方法的。)。不支持多重继承。
//确保构造函数没有任何参数
function ClassA(){ }
//方法用原型链
ClassA.prototype.color = 'blue';
ClassA.prototype.sayColor = function(){
alert(this.color);
} function ClassB(){ }
//把 ClassB 的 prototype 属性设置成 ClassA 的实例
ClassB.prototype = new ClassA(); //新方法和属性
ClassB.prototype.name = '';
ClassB.prototype.sayName = function(){
alert(this.name);
}
3、混合方式:对象冒充的缺点,每个子类都有与父类相同的方法,这样很占空间;而原型链,子类只是指向父类的方法。但是不能多重继承。所以需要结合起来:对象冒充继承属性;原型链继承方法。
通过对象冒充方式继承时,所有的成员方法都是指向this的,也就是说new之后,每个实例将都会拥有这个成员方法,并不是共用的,这就造成了大量的内存浪费。并且通过对象冒充的方式,无法继承通过prototype方式定义的变量和方法(与我想的一样)
//父类属性用构造函数
function ClassA(sColor) {
this.color = sColor;
}
//不变的用原型链
ClassA.prototype.sayColor = function () {
alert(this.color);
};
//子类构造函数用对象冒充继承
function ClassB(sColor, sName) {
ClassA.call(this, sColor);
this.name = sName;
}
//方法用原型链继承
ClassB.prototype = new ClassA();
//
ClassB.prototype.constructor = ClassB
//新方法写在最后
ClassB.prototype.sayName = function () {
alert(this.name);
};
注意:所谓的新属性,在对象冒充中是this.name。在原型链中是prototype.name。
instanceof深入学习
(1)值类型:数值、布尔值、null、undefined。
(2)引用类型:对象、数组、函数。
instanceof为了弥补typeof的不足,作用:实例是否属于某种类型;实例是否属于它的父类型;
新概念:显示原型,隐式原型:新概念,哈哈
真难:http://www.ibm.com/developerworks/cn/web/1306_jiangjj_jsinstanceof/
http://www.alloyteam.com/2015/06/javascript-shu-ju-jie-gou-he-suan-fa-jian-shu-qian-yan/
继承有三种方式:
1、
之前提到的混合方式
2、YUI继承
function Animal() {}
Animal.prototype.feeling = 'happy';
function extend(Child, Parent) {
var F = function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
extend(Dog, Animal);
var dog = new Dog('二狗', '哈士奇');
print(dog.feeling); // happy
3、jquery继承
function Animal() {}
Animal.prototype.feeling = 'happy';
function deepCopy(Child, Parent) {
var p = Parent.prototype;
var c = Child.prototype;
for (var i in p) {
if (typeof p[i] === 'object') {
c[i] = (p[i].constructor === Array) ? [] : {};
deepCopy(p[i], c[i]);
} else {
c[i] = p[i];
}
}
}
deepCopy(Dog, Animal);
var dog = new Dog('二狗', '哈士奇');
print(dog.feeling); // happy
看情况用吧。
明白了
混合继承时,为什么要加:ClassB.prototype.constructor = ClassB
这篇教程写的很好,自己现在记录一下:http://www.jb51.net/article/22334.htm
重新覆盖prototype后,这条链上的对象和方法的constructor都变为object,为了纠正,需要把constructor重新定义。
对象继承 一般用混合方式比较好,w3cschool上的例子很清楚。
YUI的更高效和简洁。
js 面向对象 继承机制的更多相关文章
- js面向对象继承
前言 最近看到js面向对象这章节了,主要学习了原型和面向对象继承关系,为了梳理自己的知识逻辑,特此记录. js的面向对象 先说说我目前了解的js创建对象方法 1.写一个函数,然后通过new创建对象 2 ...
- 27、理解js的继承机制(转载自阮一峰)
Javascript继承机制的设计思想 作者: 阮一峰 日期: 2011年6月 5日 我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类&qu ...
- js面向对象 继承
1.类的声明 2.生成实例 3.如何实现继承 4.继承的几种方式 1.类的声明有哪些方式 <script type="text/javascript"> //类的声明 ...
- 关于JS面向对象继承问题
1.原型继承(是JS中很常用的一种继承方式) 子类children想要继承父类father中的所有的属性和方法(私有+公有),只需要让children.prototype=new father;即可. ...
- js 面向对象 继承
继承方式有四种: 1.call 2.apply 3.prototype 4.for in call 和 apply 的主要区别: call 传参数只能一个一个的传, apply 因为是用数组,所以可以 ...
- JS 面向对象 ~ 继承的7种方式
前言: 继承 是 OO 语言中的一个最为人津津乐道的概念.许多 OO 语言都支持两种继承方式:接口继承 和 实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.如前所述,由于函数没有签名,在 ...
- Javascript继承机制总结 [转]
转自:http://bbs.csdn.net/topics/260051906 Javascript继承 一直想对Javascript再次做一些总结,正好最近自己写了一个小型Js UI库,总结了一下J ...
- js面向对象之继承那点事儿根本就不是事
继承 说道这个继承,了解object-oriented的朋友都知道,大多oo语言都有两种,一种是接口继承(只继承方法签名):一种是实现继承(继承实际的方法) 奈何js中没有签名,因而只有实现继承,而且 ...
- js面向对象设计之class继承
EcmaScript 2015 (又称ES6)通过一些新的关键字,使类成为了JS中一个新的一等公民.但是目前为止,这些关于类的新关键字仅仅是建立在旧的原型系统上的语法糖,所以它们并没有带来任何的新特性 ...
随机推荐
- 疯狂JAVA——第三章 数据类型和运算符
3.1注释 1.单行注释 2.多行注释 3.文档注释——文档注释以斜线后紧跟两个星号(/**)开始,以星号后紧跟一个斜线结束(*/),中间部分都是文档注释,会被提取到API文档中. API文档类似于产 ...
- python 形参
def fun(x="dx",y="dy"): print "fun------" print x print y fun()fun(&qu ...
- eclispe 通过git向码云上传
本文将介绍如何将本地的项目提交到开源中国上去,过程比较详细,实现起来很简单.由于自己也算是一个新手,所以没有做过多的解释,只是单纯的描述了该如何去做. 1.在开源中国上面新建一个空项目 到这里也就结束 ...
- List<?>和List<T>的区别
是java泛型的两种用法:List<T>是泛型方法,List<?>是限制通配符 List<T>一般有两种用途:1.定义一个通用的泛型方法.伪代码: public i ...
- Python+Webdriver,中文前加u是unicode格式编码的意思
Python+Webdriver写脚本时,对一些输入框赋值会涉及到输入中文,这时需要在中文前加u 举个例子,在用百度搜索时,要在搜索输入框内输入值, 我用的编码格式是utf-8,向输入框内输入值是:d ...
- XAMPP下apache部署网站,多个虚拟机(空间)配置
之 前在 Mac 下一直使用 MAMP 搭建本地 php 环境,因为其强大的组合配置以及方便的 UI 操作.因为公司的电脑是 Windows 的,有时候需要搭建 php 环境来调试一些小东西方便自己 ...
- mysql中float、double、decimal三种类型,以及数值产生误差的原因
单精度浮点数用4字节(32bit)表示浮点数,采用IEEE754标准的计算机浮点数,在内部是用二进制表示的,如:7.22用32位二进制是表示不下的,所以就导致不精确了,存取会出现误差. mysql中f ...
- DataTable的序列化和反序列化
/// <summary> /// DataTable序列化 /// </summary> /// <param name="dt"></ ...
- linux-Centos 7下mysql 5.7.9的rpm包安装
操作系统:Centos 7.1 mysql数据库版本:mysql5.7.18 1.安装新版mysql之前,我们需要将系统自带的mariadb-lib卸载 [root@123 ~]# rpm -qa|g ...
- 5 个关键点!优化你的 UI 原型设计
当你和你的团队着手开始一个产品开发的时候,最开始的一步一般是绘制线框图,这是大部分产品项目的第一步,它不复杂但是却对整个产品的完成形态和质量有着至关重要的作用. 很多刚开始工作设计师或者产品经理都会提 ...