精华内容
下载资源
问答
  • ES5 6 方式可以实现继承,分别为: 1. 原型链继承 原型链继承的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。 function SuperType() { this.name = 'Yvette'; this.colors = ['pink...

    ES5 有 6 种方式可以实现继承,分别为:

    1. 原型链继承

    原型链继承的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。

    function SuperType() {
        this.name = 'Yvette';
        this.colors = ['pink', 'blue', 'green'];
    }
    SuperType.prototype.getName = function () {
        return this.name;
    }
    function SubType() {
        this.age = 22;
    }
    SubType.prototype = new SuperType();
    SubType.prototype.getAge = function() {
        return this.age;
    }
    SubType.prototype.constructor = SubType;
    let instance1 = new SubType();
    instance1.colors.push('yellow');
    console.log(instance1.getName()); //'Yvette'
    console.log(instance1.colors);//[ 'pink', 'blue', 'green', 'yellow' ]
    
    let instance2 = new SubType();
    console.log(instance2.colors);//[ 'pink', 'blue', 'green', 'yellow' ]

    缺点:

    1. 通过原型来实现继承时,原型会变成另一个类型的实例,原先的实例属性变成了现在的原型属性,该原型的引用类型属性会被所有的实例共享。
    2. 在创建子类型的实例时,没有办法在不影响所有对象实例的情况下给超类型的构造函数中传递参数。

    2. 借用构造函数

    借用构造函数的技术,其基本思想为:

    在子类型的构造函数中调用超类型构造函数。

    function SuperType(name) {
        this.name = name;
        this.colors = ['pink', 'blue', 'green'];
    }
    function SubType(name) {
        SuperType.call(this, name);
    }
    let instance1 = new SubType('Yvette');
    instance1.colors.push('yellow');
    console.log(instance1.colors);//['pink', 'blue', 'green', yellow]
    
    let instance2 = new SubType('Jack');
    console.log(instance2.colors); //['pink', 'blue', 'green']

    优点:

    1. 可以向超类传递参数
    2. 解决了原型中包含引用类型值被所有实例共享的问题

    缺点:

    1. 方法都在构造函数中定义,函数复用无从谈起,另外超类型原型中定义的方法对于子类型而言都是不可见的。

    3. 组合继承(原型链 + 借用构造函数)

    组合继承指的是将原型链和借用构造函数技术组合到一块,从而发挥二者之长的一种继承模式。基本思路:

    使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承,既通过在原型上定义方法来实现了函数复用,又保证了每个实例都有自己的属性。

    function SuperType(name) {
        this.name = name;
        this.colors = ['pink', 'blue', 'green'];
    }
    SuperType.prototype.sayName = function () {
        console.log(this.name);
    }
    function SuberType(name, age) {
        SuperType.call(this, name);
        this.age = age;
    }
    SuberType.prototype = new SuperType();
    SuberType.prototype.constructor = SuberType;
    SuberType.prototype.sayAge = function () {
        console.log(this.age);
    }
    let instance1 = new SuberType('Yvette', 20);
    instance1.colors.push('yellow');
    console.log(instance1.colors); //[ 'pink', 'blue', 'green', 'yellow' ]
    instance1.sayName(); //Yvette
    
    let instance2 = new SuberType('Jack', 22);
    console.log(instance2.colors); //[ 'pink', 'blue', 'green' ]
    instance2.sayName();//Jack

    缺点:

    1. 无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。

    优点:

    1. 可以向超类传递参数
    2. 每个实例都有自己的属性
    3. 实现了函数复用

    4. 原型式继承

    原型继承的基本思想:

    借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。

    function object(o) {
        function F() { }
        F.prototype = o;
        return new F();
    }

    在 object() 函数内部,先创建一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回了这个临时类型的一个新实例,从本质上讲,object() 对传入的对象执行了一次浅拷贝。

    ECMAScript5通过新增 Object.create()方法规范了原型式继承。这个方法接收两个参数:一个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象(可以覆盖原型对象上的同名属性),在传入一个参数的情况下,Object.create() 和 object() 方法的行为相同。

    var person = {
        name: 'Yvette',
        hobbies: ['reading', 'photography']
    }
    var person1 = Object.create(person);
    person1.name = 'Jack';
    person1.hobbies.push('coding');
    var person2 = Object.create(person);
    person2.name = 'Echo';
    person2.hobbies.push('running');
    console.log(person.hobbies);//[ 'reading', 'photography', 'coding', 'running' ]
    console.log(person1.hobbies);//[ 'reading', 'photography', 'coding', 'running' ]

    在没有必要创建构造函数,仅让一个对象与另一个对象保持相似的情况下,原型式继承是可以胜任的。

    缺点:

    1. 同原型链实现继承一样,包含引用类型值的属性会被所有实例共享。

    5. 寄生式继承

    寄生式继承是与原型式继承紧密相关的一种思路。寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部已某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象。

    function createAnother(original) {
        var clone = object(original);//通过调用函数创建一个新对象
        clone.sayHi = function () {//以某种方式增强这个对象
            console.log('hi');
        };
        return clone;//返回这个对象
    }
    var person = {
        name: 'Yvette',
        hobbies: ['reading', 'photography']
    };
    
    var person2 = createAnother(person);
    person2.sayHi(); //hi

    基于 person 返回了一个新对象 -—— person2,新对象不仅具有 person 的所有属性和方法,而且还有自己的 sayHi() 方法。在考虑对象而不是自定义类型和构造函数的情况下,寄生式继承也是一种有用的模式。

    缺点:

    1. 使用寄生式继承来为对象添加函数,会由于不能做到函数复用而效率低下。
    2. 同原型链实现继承一样,包含引用类型值的属性会被所有实例共享。

    6. 寄生组合式继承

    所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法,基本思路:

    不必为了指定子类型的原型而调用超类型的构造函数,我们需要的仅是超类型原型的一个副本,本质上就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。寄生组合式继承的基本模式如下所示:

    function inheritPrototype(subType, superType) {
        var prototype = object(superType.prototype); //创建对象
        prototype.constructor = subType;//增强对象
        subType.prototype = prototype;//指定对象
    }
    • 第一步:创建超类型原型的一个副本
    • 第二步:为创建的副本添加 constructor 属性
    • 第三步:将新创建的对象赋值给子类型的原型

    至此,我们就可以通过调用 inheritPrototype 来替换为子类型原型赋值的语句:

    function SuperType(name) {
        this.name = name;
        this.colors = ['pink', 'blue', 'green'];
    }
    //...code
    function SuberType(name, age) {
        SuperType.call(this, name);
        this.age = age;
    }
    SuberType.prototype = new SuperType();
    inheritPrototype(SuberType, SuperType);
    //...code

    优点:

    只调用了一次超类构造函数,效率更高。避免在SuberType.prototype上面创建不必要的、多余的属性,与其同时,原型链还能保持不变。

    因此寄生组合继承是引用类型最理性的继承范式。

     

     

     

     

    展开全文
  • 本篇分享的是:【 继承有几种方式,分别是什么?想要实现继承可以使用什么方法? 】 (1)背景介绍: 对象:“无序属性的结合,其属性值可以包含基本值、对象或者函数”。 面向对象编程(OOP):核心思想是将...

    这里是修真院前端小课堂,每篇分享文从

    【背景介绍】【知识剖析】【常见问题】【解决方案】【编码实战】【扩展思考】【更多讨论】【参考文献】

    八个方面深度解析前端知识/技能。

    本篇分享的是:【 继承有几种方式,分别是什么?想要实现继承可以使用什么方法?  】

     

    (1)背景介绍:

    对象:“无序属性的结合,其属性值可以包含基本值、对象或者函数”。

    面向对象编程(OOP):核心思想是将各种复杂关系,抽象成一个个对象,然后由对象之间的分工合作,完成对真实世界的模拟。

    在JS中继承是一个非常复杂的话题,比其他任何面向对象语言中的继承都复杂得多。在大多数其他面向对象语言中,继承一个类只需使用一个关键字即可。在JS中想要达到继承公用成员的目的,需要采取一系列措施。

    (2)知识剖析:

    JavaScript语言的对象体系,不是基于“类”,而是基于构造函数(constructor)和原型(prototype)

    原型对象:只要创建一个新函数,就会根据特定的规则为该函数创建一个prototype属性指向其原型对象,默认情况下原型对象会自动获得一个constructor属性,该属性包含一个指向prototype属性所在函数的指针

     

    构造函数:本身是一个函数,出于创建特定类型新对象的目的而定义的,内部使用this变量,需要和new配合使用来创建实例,this变量会绑定在实例对象上。

    封装模式:将“属性”和“方法”封装成对象的模式,即创建对象的方式

     

     

     

     

     

     

    继承概念

    许多OO语言都支持两种继承方式:接口继承和实现继承,接口继承只继承方法签名,实现继承则继承实际的方法

     

    (3)常见问题:

    js如何实现继承?

    (4)解决方案:

     

    Cat如何继承Animal的species属性

     

     

     

     

     

    (5)编码实战:

    现阶段中运用比较广泛的是组合式继承,因为原型链和构造函数继承方式都有相对应的缺点,比如说原型链最主要的问题来自包含引用类型值的原型。而构造函数的缺点是不能很好地封装对象方法。一般情况下只有对象没有方法的情况下才会使用构造函数。而组合式继承继承了原型链和构造函数的优点,并完善了二者的不足。function Fn1(){

    this.colors=["red","blue","green"];

    }

    function Fn2(){

    }

    Fn2.prototype=new Fn1();//继承了Fn1()对象

    var instance1 = new Fn2();

    instance1.colors.push("black");

    console.log(instance1.colors);//"red","blue","green","black"

    var instance2 = new Fn2();

    console.log(instance2.colors);//"red","blue","green","black"

     

    (6)拓展思考:

    ES6中JavaScript拥有类的概念了,参考java等语言思考JavaScript如何使用类来简化封装、继承。

    (7)参考文献:

    参考:阮一峰的网络日志

    参考:JavaScript高级程序设计

    (8)更多讨论:

    Q1:继承一般用到什么地方?

    A :通常在一般的项目里不需要,因为应用简单,但你要用纯js做一些复杂的工具或框架系统就要用到了,比如webgis、或者js框架如jquery、angular、vue什么的,不然一个几千行代码的框架不用继承得写几万行,甚至还无法维护。

    Q2:如何确定原型和实例之间的关系? 

    A:两种方法:第一种是使用instanceOf操作符,第二种是使用isPrototypeOf()方法。 

    eg:

    console.log(person instanceOf Child);//true 

    console.log(Child.prototype.isPrototypeOf(instance));//true 

    Q3:什么是浅复制?

    A :浅复制是复制引用,复制后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响。

    (9)鸣谢:

    感谢冯强师兄,此教程是在他们之前技术分享的基础上完善而成。

    (10)结束语:

    今天的分享就到这里啦,欢迎大家点赞、转发、留言、拍砖~

     

    PPT链接 视频链接

     

    ------------------------------------------------------------------------------------------------------------

    “我们相信人人都可以成为一个工程师,现在开始,找个师兄,带你入门,学习的路上不再迷茫。”

    技能树·IT修真院:https://www.jnshu.com

    展开全文
  • 简单回顾一下构造函数、原型和实例的关系:每 个构造函数都一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型 对象的内部指针。那么,假如我们让原型对象等于另一个类型的实例,结果...

    js中实现继承

    原型链继承

    ECMAScript 中描述了原型链的概念,并将原型链作为实现继承的主要方法。其基本思想是利用原 型让一个引用类型继承另一个引用类型的属性和方法。简单回顾一下构造函数、原型和实例的关系:每 个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型 对象的内部指针。那么,假如我们让原型对象等于另一个类型的实例,结果会怎么样呢?显然,此时的 原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数 的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实 例与原型的链条。这就是所谓原型链的基本概念。

    实现原型链有一种基本模式,其代码大致如下:

    
    function Animal() {
    
        this.species = "动物";
    
        this.footers = ["一只", "两只", "三只"];
    
        this.seeHi = function () {
    
            console.log("我是" + this.name)
    
        };
    
    }
    
    
    
    function Cat() {
    
        this.name = "cat"
    
    }
    
    
    
    Cat.prototype = new Animal();//继承
    
    
    
    
    
    console.log("Cat构造函数是" + Cat.constructor);
    
    console.log("Cat原型对象是" + Cat.prototype);
    
    
    
    
    
    var cat1 = new Cat();//创建实例
    
    console.log("cat1构造函数是" + cat1.constructor);
    
    console.log("cat1原型对象是" + cat1.prototype); //因为cat1是实例,>cat1原型对象是undefined
    
    console.log("cat1原型对象是" + cat1.__proto__); //因为cat1是实例,__proto_指针指向原型对象
    
    cat1.footers.push("四只");
    
    var cat2 = new Cat();
    
    console.log(cat1.species);//>"动物"
    
    console.log(cat1.footers);//>["一只", "两只", "三只","四只"]
    
    console.log(cat2.species);//>"动物"
    
    console.log(cat2.footers);//>["一只", "两只", "三只","四只"]
    
    

    原型链继承的缺点

    1. 原型中包含引用类型值,子类修改该值,会修改引用类型的值。

    2. 在创建子类型的实例时,不能向超类型的构造函数中传递参数。

    构造函数继承

    在解决原型中包含引用类型值所带来问题的过程中,开发人员开始使用一种叫做借用构造函数 (constructor stealing)的技术(有时候也叫做伪造对象或经典继承)。这种技术的基本思想相当简单,即 在子类型构造函数的内部调用超类型构造函数。

    所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。

    
    function Animal() {
    
        this.species = "动物";
    
        this.footers = ["一只", "两只", "三只"];
    
    }
    
    function Cat(name, color) {
    
        Animal.call(this);//继承
    
        this.name = name;
    
        this.color = color;
    
    }
    
    
    
    var cat1 = new Cat("大毛","黄色");
    
    cat1.footers.push("四只");
    
    var cat2 = new Cat("二毛","红色");
    
    
    
    console.log(cat1.name);//>大毛
    
    console.log(cat1.species);//>动物
    
    console.log(cat1.footers);// >["一只", "两只", "三只","四只"]
    
    console.log(cat2.name);//>二毛
    
    console.log(cat2.species);//>动物
    
    console.log(cat2.footers);// >["一只", "两只", "三只"]
    
    

    构造函数的缺点

    如果仅仅是借用构造函数,那么也将无法避免构造函数模式存在的问题——方法都在构造函数中定 义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的,结 果所有类型都只能使用构造函数模式。考虑到这些问题,借用构造函数的技术也是很少单独使用的.

    组合继承

    组合继承(combination inheritance),有时候也叫做伪经典继承,指的是将原型链和借用构造函数的 技术组合到一块,从而发挥二者之长的一种继承模式。其背后的思路是使用原型链实现对原型属性和方 法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数 复用,又能够保证每个实例都有它自己的属性。

    
    function Animal(name) {
    
        this.species = "动物";
    
        this.name = name;
    
        this.footers = ["一只", "两只", "三只"];
    
    }
    
    Animal.prototype.sayName =function () {
    
        console.log("我的名字是"+ this.name)
    
    };
    
    function Cat(name,age) {
    
        Animal.call(this, name);//继承属性
    
        this.age = age;
    
    }
    
    //继承方法
    
    Cat.prototype = new Animal();//第一行
    
    Cat.prototype.constructor = Cat;//第二行
    
    /*
    
    *第一行相当于完全删除了prototype 对象原先的值,然后赋予一个新值。
    
    *任何一个prototype对象都有一个constructor属性,指向它的构造函数。如果没有"Cat.prototype = new Animal();"这一行,Cat.prototype.constructor是指向Cat的;
    
    * 加了这一行以后,Cat.prototype.constructor指向Animal。更重要的是,每一个实例也有一个constructor属性,默认调用prototype对象的constructor属性。
    
    * 因此,在运行"Cat.prototype = new Animal();"这一行之后,cat1.constructor也指向Animal!
    
    *这显然会导致继承链的紊乱(cat1明明是用构造函数Cat生成的),因此我们必须手动纠正,将Cat.prototype对象的constructor值改为Cat。这就是第二行的意思。
    
    */
    
    Cat.prototype.sayAge = function () {
    
        console.log("我的年龄是"+ this.age)
    
    };
    
    var cat1 = new Cat("大毛",2);
    
    cat1.footers.push("四只");
    
    var cat2 = new Cat("二毛",1);
    
    
    
    console.log(cat1.name);//>大毛
    
    console.log(cat1.sayAge());//>我的年龄是2
    
    console.log(cat1.footers);// >["一只", "两只", "三只","四只"]
    
    console.log(cat2.name);//>二毛
    
    console.log(cat2.sayAge());//>我的年龄是1
    
    console.log(cat2.footers);// >["一只", "两只", "三只"]
    
    

    组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为 JavaScript 中常用的继 承模式。而且,instanceof 和 isPrototypeOf()也能够用于识别基于组合继承创建的对象。

    原型式继承

    道格拉斯·克罗克福德在 2006年写了一篇文章,题为 Prototypal Inheritance in JavaScript (JavaScript 中的原型式继承)。在这篇文章中,他介绍了一种实现继承的方法,这种方法并没有使用严格意义上的 构造函数。他的想法是借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。为 了达到这个目的,他给出了如下函数。

    
    function object(o) {
    
        function F() {
    
        }
    
    
    
        F.prototype = o;
    
        return new F();
    
    }
    
    

    在 object()函数内部,先创建了一个临时性的构造函数,然后将传入的对象作为这个构造函数的 原型,后返回了这个临时类型的一个新实例。从本质上讲,object()对传入其中的对象执行了一次

    浅复制。来看下面的例子。

    
    var person = {name: "Nicholas", friends: ["Shelby", "Court", "Van"]};
    
    
    
    var anotherPerson = object(person);
    
    anotherPerson.name = "Greg";
    
    anotherPerson.friends.push("Rob");
    
    
    
    var yetAnotherPerson = object(person);
    
    yetAnotherPerson.name = "Linda";
    
    yetAnotherPerson.friends.push("Barbie");
    
    
    
    console.log(person.friends); //>"Shelby,Court,Van,Rob,Barbie"
    
    

    克罗克福德主张的这种原型式继承,要求你必须有一个对象可以作为另一个对象的基础。如果有这么 一个对象的话,可以把它传递给 object()函数,然后再根据具体需求对得到的对象加以修改即可。在这 个例子中,可以作为另一个对象基础的是 person 对象,于是我们把它传入到 object()函数中,然后该 函数就会返回一个新对象。这个新对象将 person 作为原型,所以它的原型中就包含一个基本类型值属性 和一个引用类型值属性。这意味着 person.friends 不仅属于 person 所有,而且也会被 anotherPerson 以及 yetAnotherPerson 共享。实际上,这就相当于又创建了 person 对象的两个副本。

    ECMAScript 5通过新增 Object.create()方法规范化了原型式继承。这个方法接收两个参数:一 个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。在传入一个参数的情况下, Object.create()与 object()方法的行为相同。

    
    var person = {name: "Nicholas", friends: ["Shelby", "Court", "Van"]};
    
    
    
    var anotherPerson = Object.create(person);
    
    anotherPerson.name = "Greg";
    
    anotherPerson.friends.push("Rob");
    
    var yetAnotherPerson = Object.create(person);
    
    yetAnotherPerson.name = "Linda";
    
    yetAnotherPerson.friends.push("Barbie");
    
    
    
    alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"
    
    

    Object.create()方法的第二个参数与Object.defineProperties()方法的第二个参数格式相 同:每个属性都是通过自己的描述符定义的。以这种方式指定的任何属性都会覆盖原型对象上的同名属 性。例如:

    
    var person = {
    
        name: "Nicholas",
    
        friends: ["Shelby", "Court", "Van"]
    
    };
    
    var anotherPerson = Object.create(person,
    
        {
    
            name: {
    
                value: "Greg"
    
            }
    
        });
    
    alert(anotherPerson.name); //"Greg"
    
    

    注意事项

    支持 Object.create()方法的浏览器有 IE9+、Firefox 4+、Safari 5+、Opera 12+和 Chrome。 在没有必要兴师动众地创建构造函数,而只想让一个对象与另一个对象保持类似的情况下,原型式 继承是完全可以胜任的。不过别忘了,包含引用类型值的属性始终都会共享相应的值,就像使用原型模 式一样。

    寄生式继承

    寄生式(parasitic)继承是与原型式继承紧密相关的一种思路,并且同样也是由克罗克福德推而广 之的。寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该 函数在内部以某种方式来增强对象,后再像真地是它做了所有工作一样返回对象。以下代码示范了寄 生式继承模式。

    
    function createAnother(original) {
    
        var clone = object(original); //通过调用函数创建一个新对象    
    
        clone.sayHi = function () { //以某种方式来增强这个对象        
    
            alert("hi");
    
        };
    
        return clone; //返回这个对象
    
    }
    
    

    在这个例子中,createAnother()函数接收了一个参数,也就是将要作为新对象基础的对象。然 后,把这个对象(original)传递给 object()函数,将返回的结果赋值给 clone。再为 clone 对象 添加一个新方法 sayHi(),后返回 clone 对象。可以像下面这样来使用 createAnother()函数:

    
    var person = {
    
        name: "Nicholas",
    
        friends: ["Shelby", "Court", "Van"]
    
    };
    
    
    
    var anotherPerson = createAnother(person);
    
    anotherPerson.sayHi(); //"hi"
    
    

    这个例子中的代码基于 person 返回了一个新对象——anotherPerson。新对象不仅具有 person 的所有属性和方法,而且还有自己的 sayHi()方法。 在主要考虑对象而不是自定义类型和构造函数的情况下,寄生式继承也是一种有用的模式。前面示 范继承模式时使用的 object()函数不是必需的;任何能够返回新对象的函数都适用于此模式。

    寄生组合式继承

    所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。其背 后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型 原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型 的原型。寄生组合式继承的基本模式如下所示。

    
    function inheritPrototype(subType, superType) {
    
        var prototype = object(superType.prototype); //创建对象    
    
        prototype.constructor = subType; //增强对象    
    
        subType.prototype = prototype; //指定对象
    
    }
    
    

    这个示例中的 inheritPrototype()函数实现了寄生组合式继承的简单形式。这个函数接收两 个参数:子类型构造函数和超类型构造函数。在函数内部,第一步是创建超类型原型的一个副本。第二 步是为创建的副本添加 constructor 属性,从而弥补因重写原型而失去的默认的 constructor 属性。 后一步,将新创建的对象(即副本)赋值给子类型的原型。这样,我们就可以用调用 inherit- Prototype()函数的语句,去替换前面例子中为子类型原型赋值的语句了,例如:

    
    function SuperType(name) {
    
        this.name = name;
    
        this.colors = ["red", "blue", "green"];
    
    }
    
    
    
    SuperType.prototype.sayName = function () {
    
        alert(this.name);
    
    };
    
    
    
    function SubType(name, age) {
    
        SuperType.call(this, name);
    
        this.age = age;
    
    }
    
    
    
    inheritPrototype(SubType, SuperType);
    
    
    
    SubType.prototype.sayAge = function () {
    
        alert(this.age);
    
    };
    
    

    这个例子的高效率体现在它只调用了一次 SuperType 构造函数,并且因此避免了在 SubType. prototype 上面创建不必要的、多余的属性。与此同时,原型链还能保持不变;因此,还能够正常使用 instanceof 和 isPrototypeOf()。开发人员普遍认为寄生组合式继承是引用类型理想的继承范式。

    参考资料

    Javascript 原型链之原型对象、实例和构造函数三者之间的关系

    编程思想:面向对象和面向过程

    Javascript面向对象编程(二):构造函数的继承

    《JavaScript高级编程设计》 第三版

    展开全文
  • 在mapreduce中分为3大join逻辑,分别的是Map端的join,reduce端的join,semi join  1>map 端的join实现逻辑:首先他会2个map任务,第一个Map任务会将小表的数据完全加载到内存中,并且将数据映射成hashmap...

    在mapreduce中分为3大join逻辑,分别的是Map端的join,reduce端的join,semi  join

          1>map 端的join实现逻辑:首先他会有2个map任务,第一个Map任务会将小表的数据完全加载到内存中,并且将数据映射成hashmap的数据结构,在该结构中key就是对应的我们连接的那个key,第2个map任务会去扫描大表的数据,与小表中的数据的key去匹配,如果相等,就进行一个连接操作

        2>reduce端的join:map任务会将将每个表映射成k,v的数据结构,并对表的数据进行打入来源标记,在reduce任务中,获取2张表享同的key就进行一个连接操作

       3>semi join:该join的是实现其实就是reduce端join 的一个优化 ,会在map端过滤掉不能join的数据,这样就可以减少数据的传输,减少磁盘io.

    展开全文
  • MapReduce 中的两表 join 几种方案简介

    千次阅读 2013-12-09 21:37:33
    1. 概述 在传统数据库(如:MYSQL)中,JOIN操作是...本文首先介绍了Hadoop上通常的JOIN实现方法,然后给出了几种针对不同输入数据集的优化方法。 2. 常见的join方法介绍 假设要进行join的数据分别来自File
  • 常见的几种排序算法

    2018-08-16 16:35:13
    冒泡的实现在细节上可以很多变化,我们将分别就3不同的冒泡实现代码,来讲解冒泡排序的思想。 2.简单选择排序 3.直接插入排序 4.希尔排序 5.堆排序 6.归并排序 7.快速排序...
  • 几种常见排序算法

    2015-10-26 15:40:05
    本文介绍几种常见的排序算法及其C实现。介绍的排序算法:冒泡法、直接插入法、直接选择法。 1、冒泡法。冒泡法排序按照大小顺序和冒泡方向分可以分为四种:分别为:元素从小到大、从左到右排;元素从小到大、从右...
  • 不同的场景不同的优化方式,总得来说,一般分治,分支界限,贪心,动态规划等思想。 循环优化 每编程语言都会强调需要优化循环。当使用 Python 的时候,你可以依靠大量的技巧使得循环运行得更快。然...
  • Java中几种常量池比较

    千次阅读 2018-07-24 19:55:32
    目录 ...Java中主要常量池,分别是class常量池、字符串常量池和运行时常量池。我们对这三个常量池进行对比。 class常量池 我们写的每一个Java类被编译之后都会生成一个对应的Class文件。Cl...
  • 快速排序的几种实现

    2014-05-06 23:13:34
    它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整...
  • 1. 概述 在传统数据库(如:MYSQL)中,JOIN操作是...本文首先介绍了Hadoop上通常的JOIN实现方法,然后给出了几种针对不同输入数据集的优化方法。 2. 常见的join方法介绍 假设要进行join的数据分别来自File
  • 其中一维搜索方法这种思想,在图像二值化里面应用。像二维码算法里面的条形码二值化,就是这种算法的进阶版。 缺点是只能按照一个方向进行搜索,且步伐需要调整。 目录: 数学期望例子 一维搜索方法求极值 ...
  • 进行图像相似度对比的几种办法

    万次阅读 2018-08-23 14:31:09
    方法描述:两幅图像patch(当然也可是整幅图像),分别计算两幅图像的直方图,并将直方图进行归一化,然后按照某种距离度量的标准进行相似度的测量。 方法的思想:基于简单的向量相似度来对图像相似度进行度量。 ...
  • 首先,博主最近读《Java编程思想》有感,总结了记住创建对象得方式,并分别列举了他们之间得关系和区别,希望对大家面向对象得思想有所启发。 博主总结Java中5创建对象的方式,下面给出它们的例子还有它们的测试...
  • 作为一典型的分而治之思想的算法应用,归并排序的实现由两方法: 1. 自上而下的递归(所有递归的方法都可以用迭代重写,所以就了第 2 方法); 2. 自下而上的迭代; 和选择排序一样,归并排序的性能不受...
  • 方法描述:两幅图像patch(当然也可是整幅图像),分别计算两幅图像的直方图,并将直方图进行归一化,然后按照某种距离度量的标准进行相似度的测量。 方法的思想:基于简单的向量相似度来对图像相似度进行度量。 ...
  • 矩阵求逆的几种方法总结(C++)

    千次阅读 2017-02-20 20:00:00
    伴随矩阵的思想分别算出其伴随矩阵和行列式,再算出逆矩阵; LU分解法(若选主元即为LUP分解法: Ax=b==>PAx=Pb==>LUx=Pb==>Ly=Pb==>Ux=y ,每步重新选主元),它不同的实现; A-1=(LU)-1=U-...
  • 方法描述:两幅图像patch(当然也可是整幅图像),分别计算两幅图像的直方图,并将直方图进行归一化,然后按照某种距离度量的标准进行相似度的测量。 方法的思想:基于简单的向量相似度来对图像相似度进行度量。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 504
精华内容 201
关键字:

思想分别有几种