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=2;
        }
//写一个关于Humens的一个原型上的方法,获取到foot
        HUmens.prototype.getFoot=function () {
            return this.foot;
        };
        //写一个子类Man
        function Man() {
            this.head=1;
        }
         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>

地狱里的镰刀====欣欣

时间: 2024-10-19 18:13:31

JavaScript-原型&原型链&原型继承&组合函数的相关文章

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

ES5类 原型  原型链 继承 JavaScript中,原型是相对于构造函数(类)的叫法(或者说概念),原型链是相对于构造函数(类)的实例对象的叫法. 对于JavaScript对象,如果在对象自身上找不到该属性,那么就会向上沿着原型链继续查找该属性 创建一个ES5类 在ES5中,类是由函数名首字母大写的函数,通过关键字new创建的. 类的构造函数就是函数自身 一般情况下,ES5类的原型对象prototype是自身构造函数,该类的实例化对象的原型链对象__proto__也是该构造函数,这二者指向同

对Javascript的原型,原型链和继承的个人理解

继承是OO语言中一个最为人津津乐道的概念,也是初接触Javascript的初学者难理解的概念=.=继承主要分为两种:一种是接口继承,另一种是实现继承.而在ECMAScript中只支持实现继承,所以我们今天来讨论讨论实现继承.实现继承就是继承实际的方法,主要依靠原型链来实现.讲到这里我们就需要讨论讨论什么是原型链. 1.什么是原型 要理解原型链我们首先要知道什么是原型.我们知道每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,这个对象包含所有实例共享的属性和方法.所以我个人

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

一.序言 ??和其他面向对象的语言(如Java)不同,Javascript语言对类的实现和继承的实现没有标准的定义,而是将这些交给了程序员,让程序员更加灵活地(当然刚开始也更加头疼)去定义类,实现继承.(以下不讨论ES6中利用class.extends关键字来实现类和继承:实质上,ES6中的class.extends关键字是利用语法糖实现的) Javascript灵活到甚至可以实现接口的封装(类似Java中的Interface和implements). 二.类的实现 1.我对类的理解 ??首先,

JavaScript原型链和继承

1.概念 JavaScript并不提供一个class的实现,在ES6中提供class关键字,但是这个只是一个语法糖,JavaScript仍然是基于原型的.JavaScript只有一种结构:对象.每个对象都有一个私有属性:_proto_,这个属性指向它构造函数的原型对象(property).它的原型对象也有一个属于自己的原型对象,这样层层向上知道一个对象的属性为null.根据定义null没有原型,它是这个原型链中的最后一个环节. 几乎所有的JavaScript中的对象都是位于原型链顶端的Objec

JavaScript 原型链、继承

对象创建 javascript 中原型我们应该最熟悉,记得刚接触js时候最长说的一句话就是,万事万物皆对象,额那时的我不怎么懂,嗯...现在的我感觉说的js里这么说确实有一定的道理,可见js中对象的重要性.好的那么创建对象的方法有以下几种方式吧: 以上那对象的创建方式:字面量.构造函数.Object.create(); 原型链 记得当时项目开发中有个同事问到我的一个问题,你给我讲讲原型链呗,上网搜了张图,这张图我觉得很能诠释所有的关系列表,以及几者之间有联系,基本上很清晰: // 构造函数 ==

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

构造函数,原型,实例三者的关系 构造函数: 构造函数是创建对象的一种常用方式, 其他创建对象的方式还包括工厂模式, 原型模式, 对象字面量等.我们来看一个简单的构造函数: function Product (name, role){ //构造函数的命名约定第一个字母使用大写的形式! this.name = name; this.role = role; } ( 1 ) 每一个构造函数都有一个prototype属性,我们可以在Chorme控制台中打印出Product.prototype属性. (

JavaScript 随笔2 面向对象 原型链 继承

第六章 面向对象的程序设计 1.创建对象的几种方式 A)工厂模式 function CreatObj(name,sex,age){ this.name=name; this.sex=sex; this.age=age; } 缺点:虽然可以批量创建对象,却不能知道对象的类型 只知道他是Object类型: B)构造函数 function Person(name,sex){ this.name=name; this.sex=sex; this.sayName=function(){ alert(thi

JavaScript难点系列(六):原型链与继承

类和构造函数 JS中使用构造函数来定义类: function Range(from, to) { this.from = from this.to = to } Range.prototype.includes = function(x) { return this,from <= x && x <= this.to } Range.prototype.toString = function() { return this.from + '...' + this.to } va

javascript精髓篇之原型链维护和继承.

一.两个原型 很多人都知道javascript是原型继承,每个构造函数都有一个prototype成员,通过它就可以把javascript的继承演义的美轮美奂了.其实啊,光靠这一个属性是无法完成javascript的继承.我们在代码中使用的prototype完成继承在这里就不多说了.大家可以查一下资料.另外一个看不见的prototype成员.每一个实例都有有一条指向原型的prototype属性,这个属性是无法被访问到的,当然也就无法被修改了,因为这是维护javascript继承的基础. 1 //构