JavaScript-原型&原型链&原型继承&组合函数
小小的芝麻之旅:
今天学习了js的原型,要说原型,我们先简单说一下函数创建过程。
原型
每个函数在创建的时候js都自动添加了prototype属性,这就是函数的原型,原型就是函数的一个属性,类似一个指针。原型在函数的创建过程中由js编译器自动添加。
<script type="text/javascript">
function Flower(name,area) {
this.name=name;
this.area=area;
this.showName=myName;
}
//全局对象,浏览器 解析器 代码
function myName() {
alert(this.name);
};
//创建出一个flower对象
var f1=new Flower("好季节","待机时间苦咖啡");
f1.showName();
var f2=new Flower("接电话","你的那份你看到");
f2.showName();
if(f1.showName==f2.showName){
alert("==");
}else{
alert("!=");
}
<
/script>
原型链
在JavaScript中,每个对象都有一个[[Prototype]]属性,其保存着的地址就构成了对象的原型链
。
[[Prototype]]属性是js编译器在对象被创建时自动添加的,其取值由new运算符的右侧参数决定。字面量的方式可转化为new Obejct();
var x =new Flower();
vae o = {}; //var o = new Obejct();
通过对象的[[Prototype]]保存对另一个对象的引用,通过这个引用往上进行属性的查找,这就是原型链查找机制
。
对象在查找某个属性的时候,会首先遍历自身的属性,如果没有则会继续查找[[Prototype]]
引用的对象,如果再没有则继续查找[[Prototype]].[[Prototype]]
引用的对象,依次类推,直到[[Prototype]].….[[Prototype]]
为undefined
prototype本身是一个Object对象的实例,所以其原型链指向的是Object的原型。
<script type="text/javascript"> function HUmens(){
this.foot=;
}
//写一个关于Humens的一个原型上的方法,获取到foot
HUmens.prototype.getFoot=function () {
return this.foot;
};
//写一个子类Man
function Man() {
this.head=;
}
Man.prototype=new HUmens();
Man.prototype,getHead=function () {
return this.head;
};
var man1=new Man();
alert(man1.foot); </script>
基于原型链的继承
继承属性
JavaScript 对象是动态的属性“包”(指其自己的属性)。JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依此层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
prototype
和 Object.getPrototypeOf
prototype
和 Object.getPrototypeOf
对于从 Java 或 C++ 转过来的开发人员来说 JavaScript 会有点让人困惑,因为它全部都是动态的,都是运行时,而且不存在类(classes)。所有的都是实例(对象)。即使我们模拟出的 “类(classes)”,也只是一个函数对象。
你可能已经注意到,我们的函数 A 有一个特殊的属性叫做原型。这个特殊的属性与 JavaScript 的 new 运算符一起工作。对原型对象的引用会复制到新实例内部的
__proto__ 属性。例如,当你这样: var a1 = new A(), JavaScript 就会设置:a1.
__proto__ = A.prototype(在内存中创建对象后,并在运行 this 绑定的函数 A()之前)。然后在你访问实例的属性时,JavaScript 首先检查它们是否直接存在于该对象中(即是否是该对象的自身属性),如果不是,它会在
__proto__ 中查找。也就是说,你在原型中定义的元素将被所有实例共享,甚至可以在稍后对原型进行修改,这种变更将影响到所有现存实例。
像上面的例子中,如果你执行 var a1 = new A(); var a2 = new A(); 那么 a1.doSomething 事实上会指向Object.getPrototypeOf(a1).doSomething,它就是你在 A.prototype.doSomething 中定义的内容。比如:Object.getPrototypeOf(a1).doSomething == Object.getPrototypeOf(a2).doSomething == A.prototype.doSomething。
简而言之, prototype 是用于类型的,而 Object.getPrototypeOf() 是用于实例的(instances),两者功能一致。
__proto__ 看起来就像递归引用, 如a1.doSomething,Object.getPrototypeOf(a1).doSomething,Object.getPrototypeOf(Object.getPrototypeOf(a1)).doSomething 等等等, 直到它找到 doSomething 这个属性或者 Object.getPrototypeOf 返回 null。
关于javascript中apply()和call()方法的区别
如果没接触过动态语言,以编译型语言的思维方式去理解javaScript将会有种神奇而怪异的感觉,因为意识上往往不可能的事偏偏就发生了,甚至觉得不可理喻.如果在学JavaScript,先理解JavaScrtipt动态变换运行时上下文特性,这种特性主要就体现在apply, call两个方法的运用上.
区分apply,call就一句话,
foo.call(this, arg1,arg2,arg3) == foo.apply(this, arguments)==this.foo(arg1, arg2, arg3)
call, apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例,也就是每个方法都有call, apply属性.既然作为方法的属性,那它们的使用就当然是针对方法的了.这两个方法是容易混淆的,因为它们的作用一样,只是使用方式不同.
相同点:两个方法产生的作用是完全一样的
不同点:方法传递的参数不同
javascript继承有几种继承方式,现在来说说其中的组合继承。
组合继承是结合了原型链和借用构造函数这两种技术的继承方式,分别利用它们的长处,避免了短处。
原型链
原型链就是实例与原型之间的链条。
子类型构造函数 与 超类型构造函数 之间没有关联,只需将 子类型构造函数的原型 作为 超类型构造函数的实例。这样,子类型构造函数的实例 就可以共享 超类型构造函数原型的方法 以及 超类型构造函数的属性。
如:
var subType.prototype = new superType();
原型链的短处在于:当subType.prototype作为实例时拥有的superType构造函数里的属性,在它作为subType的原型时,这些属性就作为原型的属性被subType的实例共享;还有,因为两个类型的构造函数之间没有关联,在创建subType的实例时,不能向superType构造函数传递参数。
借用构造函数
在 子类型构造函数里 调用 超类型构造函数,使用 call() 或 apply() 方法。
如:
superType.call(this); 或 superType.call(this,参数);
通过这样可以将superType构造函数里的属性作为特定的,即subType的实例调用时,这些属性也是特属于每一个实例,而不是共享的。同时,还可以向superType构造函数传递参数。
然而,定义在superType.prototype里的方法,对subType是不可见的。
这两个方法都有其所长,也有其所短。所以将它们组合起来,这就有了组合继承。了解了原型链与借用构造函数就不难理解组合继承了。
组合继承
组合继承是通过原型链继承原型的方法,通过借用构造函数继承属性。这样就可以将属性与方法分开继承,方法被所有实例共享,而属性则是特属于每一个实例。
当然,组合继承也有其缺点,那就是超类型的属性被继承了两次,一次是子类型原型继承,另一次是子类型实例继承,只是实例继承的属性屏蔽了原型继承的属性。
加例子:
<script type="text/javascript">
function Flower() {
//空模板
}
Flower.prototype.name="大开杀戒";
Flower.prototype.area="服抗生素世界世界";
Flower.prototype.showName=function () {
alert(this.name);
};
var flag=Flower.prototype.constructor==Flower;
alert(flag);
var flower1=new Flower();
if(flower1.__proto__==flower1.prototype) {
alert("---===---");
}
</script>
地狱里的镰刀====欣欣
JavaScript-原型&原型链&原型继承&组合函数的更多相关文章
- 【转】js原型链与继承
原文链接:https://blog.csdn.net/u012468376/article/details/53127929 一.继承的概念 继承是所有的面向对象的语言最重要的特征之一.大部分的o ...
- 三张图搞懂JavaScript的原型对象与原型链 / js继承,各种继承的优缺点(原型链继承,组合继承,寄生组合继承)
摘自:https://www.cnblogs.com/shuiyi/p/5305435.html 对于新人来说,JavaScript的原型是一个很让人头疼的事情,一来prototype容易与__pro ...
- JavaScript ES5类 原型 原型链 组合、原型、寄生式继承
ES5类 原型 原型链 继承 JavaScript中,原型是相对于构造函数(类)的叫法(或者说概念),原型链是相对于构造函数(类)的实例对象的叫法. 对于JavaScript对象,如果在对象自身上找 ...
- 《JAVASCRIPT高级程序设计》根植于原型链的继承
继承是面向对象的语言中,一个最为津津乐道并乐此不疲的话题之一.JAVASCRIPT中的继承,主要是依靠原型链来实现的.上一篇文章介绍过,JAVASCRIPT中,每一个对象都有一个prototype属性 ...
- 对Javascript 类、原型链、继承的理解
一.序言 和其他面向对象的语言(如Java)不同,Javascript语言对类的实现和继承的实现没有标准的定义,而是将这些交给了程序员,让程序员更加灵活地(当然刚开始也更加头疼)去定义类,实现继承 ...
- JavaScript原型链和继承
1.概念 JavaScript并不提供一个class的实现,在ES6中提供class关键字,但是这个只是一个语法糖,JavaScript仍然是基于原型的.JavaScript只有一种结构:对象.每个对 ...
- [转]深入javascript——原型链和继承
在上一篇post中,介绍了原型的概念,了解到在javascript中构造函数.原型对象.实例三个好基友之间的关系:每一个构造函数都有一个“守护神”——原型对象,原型对象心里面也存着一个构造函数的“位置 ...
- JavaScript系列--浅析原型链与继承
一.前言 继承是面向对象(OOP)语言中的一个最为人津津乐道的概念.许多面对对象(OOP)语言都支持两种继承方式::接口继承 和 实现继承 . 接口继承只继承方法签名,而实现继承则继承实际的方法.由于 ...
- 浅谈Javascript中的原型、原型链、继承
构造函数,原型,实例三者的关系 构造函数: 构造函数是创建对象的一种常用方式, 其他创建对象的方式还包括工厂模式, 原型模式, 对象字面量等.我们来看一个简单的构造函数: function Produ ...
随机推荐
- 对Routers的理解
路由Routers 对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息. REST framework提供 ...
- SparkSQL开窗函数 row_number()
开始编写我们的统计逻辑,使用row_number()函数 先说明一下,row_number()开窗函数的作用 其实就是给每个分组的数据,按照其排序顺序,打上一个分组内行号 比如说,有一个分组20151 ...
- 实验一 c++简单程序设计
一.实验内容 1.ex 2_28 (1) 用if...else判断 #include<iostream> using namespace std; int main() { char i; ...
- 【App性能】:TraceView分析法
抓取traceview的日志有两种方式, 1,是在代码中片段中添加: Debug.startMethodTracing(“hello”); ....... Debug.stopMethodTracin ...
- Linux/Mac安装oh-my-zsh后不执行~/.bash_profile、~/.bashrc解决办法
安装了zsh之后默认启动执行脚本变为了-/.zshrc. 解决办法: Mac: 修改-/.zshrc文件,在其中添加:source -/.bash_profile.source -/.bashrc:注 ...
- Docker MySQL基本操作
1 启动mysql实例 docker run --name some-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:t ...
- 用maven来创建scala和java项目代码环境(图文详解)(Intellij IDEA(Ultimate版本)、Intellij IDEA(Community版本)和Scala IDEA for Eclipse皆适用)(博主推荐)
不多说,直接上干货! 为什么要写这篇博客? 首先,对于spark项目,强烈建议搭建,用Intellij IDEA(Ultimate版本),如果你还有另所爱好尝试Scala IDEA for Eclip ...
- [中英对照]The Art Of Reporting Bugs | 报bug的艺术
前言:因为最近要给兄弟Team分享一下如何有效地报告bug, 故多做一做功课.下面给出一篇博客的中英文对照翻译. The Art Of Reporting Bugs | 报bug的艺术 My init ...
- Intel万兆网卡背靠背连接ping不通那点事儿
对那些整天喊着“玩大的,玩狠的”口号的人来说,我下面要说的这点事儿,根本就不算事儿.所以,如果你正好喜欢喊口号,就不要往下看了,因为我要讲述的,你可能不感兴趣,也可能看不懂. 今天,是我加入I公司3个 ...
- P2P 行业解决方案
P2P指个人与个人之间的借贷,而P2P理财是指以公司为中介机构,把这借贷双方对接起来实现各自的借贷需求.借款方可以是无抵押贷款或是有抵押贷款.而中介一般是收取双方或单方的手续费为盈利目的或者是赚取一定 ...