小小的芝麻之旅:

今天学习了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

对于从 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动态变换运行时上下文特性,这种特性主要就体现在applycall两个方法的运用上.

区分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-原型&原型链&原型继承&组合函数的更多相关文章

  1. 【转】js原型链与继承

    原文链接:https://blog.csdn.net/u012468376/article/details/53127929 一.继承的概念 ​ 继承是所有的面向对象的语言最重要的特征之一.大部分的o ...

  2. 三张图搞懂JavaScript的原型对象与原型链 / js继承,各种继承的优缺点(原型链继承,组合继承,寄生组合继承)

    摘自:https://www.cnblogs.com/shuiyi/p/5305435.html 对于新人来说,JavaScript的原型是一个很让人头疼的事情,一来prototype容易与__pro ...

  3. JavaScript ES5类 原型 原型链 组合、原型、寄生式继承

    ES5类 原型  原型链 继承 JavaScript中,原型是相对于构造函数(类)的叫法(或者说概念),原型链是相对于构造函数(类)的实例对象的叫法. 对于JavaScript对象,如果在对象自身上找 ...

  4. 《JAVASCRIPT高级程序设计》根植于原型链的继承

    继承是面向对象的语言中,一个最为津津乐道并乐此不疲的话题之一.JAVASCRIPT中的继承,主要是依靠原型链来实现的.上一篇文章介绍过,JAVASCRIPT中,每一个对象都有一个prototype属性 ...

  5. 对Javascript 类、原型链、继承的理解

    一.序言   和其他面向对象的语言(如Java)不同,Javascript语言对类的实现和继承的实现没有标准的定义,而是将这些交给了程序员,让程序员更加灵活地(当然刚开始也更加头疼)去定义类,实现继承 ...

  6. JavaScript原型链和继承

    1.概念 JavaScript并不提供一个class的实现,在ES6中提供class关键字,但是这个只是一个语法糖,JavaScript仍然是基于原型的.JavaScript只有一种结构:对象.每个对 ...

  7. [转]深入javascript——原型链和继承

    在上一篇post中,介绍了原型的概念,了解到在javascript中构造函数.原型对象.实例三个好基友之间的关系:每一个构造函数都有一个“守护神”——原型对象,原型对象心里面也存着一个构造函数的“位置 ...

  8. JavaScript系列--浅析原型链与继承

    一.前言 继承是面向对象(OOP)语言中的一个最为人津津乐道的概念.许多面对对象(OOP)语言都支持两种继承方式::接口继承 和 实现继承 . 接口继承只继承方法签名,而实现继承则继承实际的方法.由于 ...

  9. 浅谈Javascript中的原型、原型链、继承

    构造函数,原型,实例三者的关系 构造函数: 构造函数是创建对象的一种常用方式, 其他创建对象的方式还包括工厂模式, 原型模式, 对象字面量等.我们来看一个简单的构造函数: function Produ ...

随机推荐

  1. 对Routers的理解

    路由Routers 对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息. REST framework提供 ...

  2. SparkSQL开窗函数 row_number()

    开始编写我们的统计逻辑,使用row_number()函数 先说明一下,row_number()开窗函数的作用 其实就是给每个分组的数据,按照其排序顺序,打上一个分组内行号 比如说,有一个分组20151 ...

  3. 实验一 c++简单程序设计

    一.实验内容 1.ex 2_28 (1) 用if...else判断 #include<iostream> using namespace std; int main() { char i; ...

  4. 【App性能】:TraceView分析法

    抓取traceview的日志有两种方式, 1,是在代码中片段中添加: Debug.startMethodTracing(“hello”); ....... Debug.stopMethodTracin ...

  5. Linux/Mac安装oh-my-zsh后不执行~/.bash_profile、~/.bashrc解决办法

    安装了zsh之后默认启动执行脚本变为了-/.zshrc. 解决办法: Mac: 修改-/.zshrc文件,在其中添加:source -/.bash_profile.source -/.bashrc:注 ...

  6. Docker MySQL基本操作

    1 启动mysql实例 docker run --name some-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:t ...

  7. 用maven来创建scala和java项目代码环境(图文详解)(Intellij IDEA(Ultimate版本)、Intellij IDEA(Community版本)和Scala IDEA for Eclipse皆适用)(博主推荐)

    不多说,直接上干货! 为什么要写这篇博客? 首先,对于spark项目,强烈建议搭建,用Intellij IDEA(Ultimate版本),如果你还有另所爱好尝试Scala IDEA for Eclip ...

  8. [中英对照]The Art Of Reporting Bugs | 报bug的艺术

    前言:因为最近要给兄弟Team分享一下如何有效地报告bug, 故多做一做功课.下面给出一篇博客的中英文对照翻译. The Art Of Reporting Bugs | 报bug的艺术 My init ...

  9. Intel万兆网卡背靠背连接ping不通那点事儿

    对那些整天喊着“玩大的,玩狠的”口号的人来说,我下面要说的这点事儿,根本就不算事儿.所以,如果你正好喜欢喊口号,就不要往下看了,因为我要讲述的,你可能不感兴趣,也可能看不懂. 今天,是我加入I公司3个 ...

  10. P2P 行业解决方案

    P2P指个人与个人之间的借贷,而P2P理财是指以公司为中介机构,把这借贷双方对接起来实现各自的借贷需求.借款方可以是无抵押贷款或是有抵押贷款.而中介一般是收取双方或单方的手续费为盈利目的或者是赚取一定 ...