javaScript-原型、继承-02
原型链
首先回顾下实列、构造函数、原型对象之间的关系;
实列都包含指向原型对象的一个指针(_proto_);
构造函数都有prototype(原型属性)指向原型对象的指针;
原型是一个对象也存在一个内部属性(_proto_)指向父类(上一级)原型对象;
那么原型链就是:实例通过 _proto_ 递归往上查找就构成实例与原型的链条(object除外,它是基类);
function Person(){ }
链图:
总结:
1、所有引用类型默认都继承Object
2、所有函数的默认原型都是Object的实例,类似于:原型对象=new Object(),因此默认原型都会包含一个内部指针(_proto_),指向Object.Prototype;
3、所有引用类型对象都有_proto_属性指向原型对象,所有function 对象都有prototype 属性,指向原型对象;
原型链-继承
我所知道的继承有两种方式:
1、接口继承:只继承方法签名;
2、实现继承:继承实际的方法;
因为js中函数没有签名所以无法实现接口继承,只支持方法继承,并且是依靠原型链来实现的;
function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; } Person.prototype.sayHello=function(){ console.log("hello word!")}; function Man(){ } Man.prototype=new Person(); var instance=new Man(); console.log(instance.sayHello);// hello word!
以上就是很简单的继承,把Man原型指针指向Person的一个实例,这样new Man()的实例就可以访问到Person中的sayHello方法,如图所示;
原型链也是存在一些问题把上面代码改下:
function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; this.color=["red","blue","green"]; } Person.prototype.sayHello=function(){ console.log("hello word!")}; function Man(){ } Man.prototype=new Person(); var instance=new Man(); instance.color.push("black"); console.log(instance.color);//["red", "blue", "green", "black"] var instance2=new Man(); console.log(instance2.color); //["red", "blue", "green", "black"]
我们知道原型是所有实例共享属性、方法,当使用原型来实现继承时,原型实际上会变成另一个类型的实例,所以就会出现上面的问题;
组合继承
组合继承的原理很简单,在构造子类对象实例的时候通过改变this 指针让子类对象实例拥有父类属性以及自身构造的属性,这样可以达到实例之间有独立的属性副本,
方法的继承还是通过原型来实现,来看代码:
function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; this.color=["red","blue","green"]; } Person.prototype.sayHello=function(){ console.log("hello word!")}; function Man(name,age,sex,job){ Person.call(this,name,age,sex); this.job=job; } Man.prototype=new Person(); var instance=new Man("张三",20,"男","农民"); instance.color.push("black"); console.log(instance.color);//["red", "blue", "green", "black"] console.log(instance.job);//农民 console.log(instance.sayHello);//hello word! var instance2=new Man("张三",20,"男","地主"); console.log(instance2.color); //["red", "blue", "green"] console.log(instance2.job);//地主 console.log(instance2.sayHello);//hello word!
通过在构造函数中指向父类,这样实例对象存在父类的属性,前面说过搜索原理是从实例开始的,那么即使是原型对象是父类的实例对象,属性还是取的是实例对象中的属性;
组合模式是JavaScript中常用的继承方式;
call、apply、bind(绑定)
JavaScript中函数可以通过3种方法改变自己的this指向,它们是call、apply、bind。它们3个非常相似,但是也有区别。下面表格可以很直观看出三者的不同
方法 | 是否直接执行函数 | 传入的参数 | 调用方式 |
call | 是 |
(context,arg1,arg2,arg3...) 第二个参数之后都是实参 |
function.call(context,arg1,arg2,arg3...) |
apply | 是 |
(context,[arg1,arg2,arg3...]) 第二个参数必须是数组 |
function.apply(context,[arg1,arg2,arg3...]) |
bind | 否 |
(context,arg1,arg2,arg3...) 第二个参数之后都是实参 |
var newFunction = function.bind(context); newFunction(arg1,arg2,arg3...) |
call和apply功能:使用指定的对象调用当前函数。call和apply的功能完全相同,只是在语法上略有不同。
call :
var a = {x: 1}; var b = function (y, z) { console.log(this.x + y + z) }; b.call(a, 3, 4);//此时b的this(即b执行时的上下文)被改变为a,因此this.x为1,第二个参数之后都是传给b实参。
apply:
var a = {x: 1}; var b = function (arr) { console.log(this.x + arr[0] + arr[1]) }; b.call(a, [3, 4]);//此时b的this(即b执行时的上下文)被改变为a,第二个参数是一个数组
bind:
var a = {x: 1}; var b = function (y, z) { console.log(this.x + y + z) }; var newB = b.bind(a);//此时b的this(即b执行时的上下文)被改变为a,由此生成一个新函数,函数不会立即执行。 newB(3, 4);//函数此时才执行
call或apply是将执行上下文对象换了后,立即执行;而bind是将执行上下文对象换了后,创建一个新函数。
function fun(){ console.log(this.name); } function obj1(){ this.name = 'call||apply'; } function obj2(){ this.name = 'bind'; } var o1 = new obj1(); var o2 = new obj2(); fun.call(o1); //手动调用bind创建的新函数 fun.bind(o2)();
在网上找了张比较完整原型链图:
总结
1、原型链的形成真正是靠 _proto_,指向原型对象;
2、引用类型默认都继承Object;
3、所有函数的默认原型都是Object 实例,即默认原型对象也有一个内部属性 _proto_指向 Object prototype 对象;
4、Function.prototype是函数类型的原型;
5、继承主要是基于原型链实现的,而原型链主要是基于实例与原型对象链条实现,引用类型任何对象都有内部属性 _proto_指向原型对象;
javaScript-原型、继承-02的更多相关文章
- 再谈javascript原型继承
Javascript原型继承是一个被说烂掉了的话题,但是自己对于这个问题一直没有彻底理解,今天花了点时间又看了一遍<Javascript模式>中关于原型实现继承的几种方法,下面来一一说明下 ...
- 彻底理解Javascript原型继承
彻底理解Javascript原型继承 之前写过一篇Javascript继承主题的文章,这篇文章作为一篇读书笔记,分析的不够深入. 本文试图进一步思考,争取彻底理解Javascript继承原理 实例成员 ...
- [转]Javascript原型继承
真正意义上来说Javascript并不是一门面向对象的语言,没有提供传统的继承方式,但是它提供了一种原型继承的方式,利用自身提供的原型属性来实现继承.Javascript原型继承是一个被说烂掉了的话题 ...
- JavaScript原型继承工作原理
原型继承的定义 当你阅读关于JS原型继承的解释时,你时常会看到以下这段文字: 当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止.——出自JavaScript秘 ...
- 【读书笔记】读《编写高质量代码—Web前端开发修炼之道》 - JavaScript原型继承与面向对象
JavaScript是基于原型的语言,通过new实例化出来的对象,其属性和行为来自于两部分,一部分来自于构造函数,另一部分是来自于原型.构造函数中定义的属性和行为的优先级比原型中定义的属性和优先级高, ...
- JavaScript 原型继承开端
1.原型继承本质 就javascript对象系统的实现来讲,对象并没有原型,而构造器有原型(构造器.prototype指向其原型).对象只有构造自某个原型的说法,并没有持有某个原型的说法. ...
- 浅析Javascript原型继承(转)
引自: http://blog.csdn.net/kittyjie/article/details/4380918 原作者解释的浅显易懂,非常不错的JavaScript prototype总结 JS没 ...
- Javascript原型继承容易忽略的错误
编写Javascript的开发者都知道,JS虽然没有类(ES6添加了class语法),但是可以模拟出OOP语言的类和面向对象的概念,比如我们都知道的一句话,Javascript中处处是对象,而面向对象 ...
- javascript原型继承圣杯模式
javascript纯面向对象开发需要使用到的一个模式,来对对象之间原型继承做中间层代理避免重复继承与代码杂乱 <!DOCTYPE html> <html lang="en ...
- javascript原型继承
在传统的基于Class的语言如Java.C++中,继承的本质是扩展一个已有的Class,并生成新的Subclass. 由于这类语言严格区分类和实例,继承实际上是类型的扩展.但是,JavaScript由 ...
随机推荐
- 数据结构——Java实现二叉树
相关概念 存储结构: 顺序存储结构:二叉树的顺序存储结构适用于完全二叉树,对完全二叉树进行顺序编号,通过二叉树的性质五(第1个结点为根结点,第i个结点的左孩子为第2i个结点,右孩子为第2i+1个结点) ...
- 嵌入式 VFS: Cannot open root device "mtdblock2" or unknown-block(2,0)
系统启动后,虽然nand驱动表现正常,但是最后挂载rootfs时候出错: Kernel command line: root=/dev/mtdblock2 rw init=/linuxrc conso ...
- SQL0668N 由于表 "db2inst1.test" 上的原因代码 "3",所以不允许操作(解因为LOAD引起的LOAD暂挂状态锁)
DB2解因为LOAD引起的LOAD暂挂状态锁 一般解锁命名是,SET INTEGRITY FOR temp_test IMMEDIATE CHECKED 但是load暂挂状态是解不了的,可以l ...
- HashBiMap
HashBiMap AbstractMap类实现了Map接口定义的一些方法,而BiMap类定义了其子类需要实现的一些方法,使得所有实现BiMap的类必须符合其独有的特性:键.值都是唯一的.HashB ...
- 什么是CC攻击,如何防止网站被CC攻击的方法总汇
CC攻击(Challenge Collapsar)是DDOS(分布式拒绝服务)的一种,也是一种常见的网站攻击方法,攻击者通过代理服务器或者肉鸡向向受害主机不停地发大量数据包,造成对方服务器资源耗尽,一 ...
- Linux目录初识
/ 根目录 /bin 存放必要的命令 /boot 存放内核以及启动所需的文件/dev 存放设备文件 /etc 存放系统配置文件 /home 普通用户的宿主目录,用户数据存放在其主目录中 /lib 存放 ...
- JavaScript 教程学习进度备忘(二)
备忘:之前,只将“JS 教程”学习完毕,这篇记录:“JS HTML DOM ”.“JS 对象”.“JS Window”.“JS 库” 书签:跳过:另外跳过的内容有待跟进 _______________ ...
- 网站压力测试工具-Webbench源码笔记
Ubuntu 下安装使用 1.安装依赖包CTAGS sudo apt-get install ctage 2.下载及安装 Webbench http://home.tiscali.cz/~cz2105 ...
- git 换行符问题
git 换行符问题 在windows环境中 对于autocrlf = false 不会激发 关于换行符的处理 对于autocrlf = true 会在提交是将LF替换成CRLF 切出时时CRLF 对于 ...
- 数往知来 SQL SERVER 基本语法<七>
sqlserver学习_01 启动数据库 开始->cmd->进入控制台 sqlcmd->-S .\sqlexpress 1> 如果出现表示数据库"sqle ...