原型与继承

来源:互联网 发布:java获取局域网所有ip 编辑:程序博客网 时间:2024/05/19 20:40

最近为了校招面试在刷基础,看了原型和继承又是各种懵比的样子。原型的问题参考大神博客深入理解JavaScript原型和闭包以及JavaScript面向对象编程

关于对象和函数的关系,简单说以下几点。

  • 函数是一种对象,而对象是通过函数创建的。
  • 函数含有prototype属性,该属性其实是属性的集合(对象),其默认属性为Constructor,Constructor指向构造函数本身。
  • 对象含有_proto_属性,该属性指向创建该对象的函数的原型。即obj._proto_ === F.prototype。
掌握以上三点,原型链要会画。

接下来说说继承。

高程给了六种继承方法:原型链继承,借用构造函数继承,组合继承,原型式继承,寄生式继承,寄生组合式继承。

本文是前三种方式的笔记~

一、原型链

    通过让B的原型对象成为A的实例,当构造B的实例时,该实例将实现对A中属性和方法的继承。

    属性和方法,分为两种,一种是私有的,一种是公有的。在原型中定义的属性和方法是公有属性,可对其进行操作,而构造函数中的属性和方法是实例私有的属性方法。

    

function SuperType() {    this.property = true;}SuperType.prototype.getSuperValue = function() {    return this.property;};function SubType() {    this.subproperty = false;}//inherit from SuperTypeSubType.prototype = new SuperType();SubType.prototype.getSubValue = function() {    return this.subproperty;};var instance = new SubType();console.log(instance.getSuperValue()); //true// SubType原型继承了Supertype的属性和方法console.log(SubType.prototype); // SuperType {property: true, getSubValue: [Function]}console.log(SubType.prototype.getSuperValue());// trueconsole.log(SubType.prototype.constructor === SuperType); // trueconsole.log(SuperType.prototype.constructor === SuperType); // trueconsole.log(instance.constructor);// [Function: SuperType]
弊端:

  1. 包含引用类型值的原型。包含引用类型值得原型属性会被所有实例共享(等会儿去翻书解决这一问题),而这也正是为什么要在构造函数中而不是在原型对象中定义属性的原因。再通过原型来实现继承时,原型实际上会变成另一个类型的实例。于是原先的实例属性也就变成了现在的原型属性。
    function SuperType() {    this.colors = ["red", "blue", "green"];}function SubType() {}//inherit from SuperTypeSubType.prototype = new SuperType();var instance1 = new SubType();instance1.colors.push("black");console.log(instance1.colors); //"red,blue,green,black"var instance2 = new SubType();console.log(instance2.colors); //"red,blue,green,black"// SubType.prototype中的colors属性被修改,并未影响到超类型的构造函数属性值的改变var instance3 = new SuperType();console.log(instance3.colors); // 'red, blue, green'

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

基本思想是在子类型构造函数的内部调用超类型构造函数。即在子类型构造函数的内部调用超类型构造函数。通过使用apply()和call()在(将来)创建的对象上执行构造函数。

function SuperType (name) {    this.name = name;}function SubType () {    SuperType.call(this,'azure');    this.age = 29;}var instance1 = new SubType();instance1.age = 23;console.log(instance1.name, instance1.age);var instance2 = new SubType();instance2.name = 'hel';console.log(instance2.name, instance2.age);

问题:方法都在构造函数中定义,因此函数复用就无从谈起了。

三、组合继承

啦啦啦结合二者之长的来啦~组合继承的思路是使用原型链实行对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承。如此,既通过在原型上定义方法实现了函数复用,又能保证每个实例都有自己的属性。

四、比较

    // case 1: 标准的组合继承    // case 2: 注释掉a、b语句,此时为原型链继承    // case 3: 注释掉b、c语句,此时为构造函数继承    function SuperType (name) {        this.name = name;        this.colors =['r', 'g', 'b'];    }    SuperType.prototype.sayName = function () {        console.log(this.name);    };    function SubType (name, age) {        // a.这一句的作用是,SubType实例将具备SuperType构造函数中的属性        SuperType.call(this, name);        this.age = age;    }    // c. 原型链继承    SubType.prototype = new SuperType();    // b.如果没有这一句,SubType.prototye.constructor指向SuperType    SubType.prototype.constructor = SubType;    SubType.prototype.sayAge = function () {        console.log(this.age);    }    // case 1 -> 指向SubType, 包含属性name,colors,constructor,sayAge(), 虽然没有sayName, 但是沿着原型链即可找到, 即SubType.protype.sayName()是存在的。    // case 2 -> 指向SuperType, 包含属性name,colors,sayAge()    // case 3 -> 指向SubType, 原型链并未改变,只是借用了构造函数, 只会对实例造成影响,并不会影响原型本身    console.log(SubType.prototype);    var instance1 = new SubType('Nico', 24);    // case 1 -> 指向SubType, 包含属性name, colors,age, 其中sayAge是SubType原型中的属性, sayName是创造SuperType实例(SubType原型)构造函数原型中的方法, 都可以通过原型链找到。    // case 2 -> 指向SuberType, 仅包含属性age, 其余都是构造函数原型中的方法    // case 3 -> 指向SubType, 包含属性name,colors(由构造函数继承而来), age, 并不能继承到sayName, 也就是说构造函数继承只可以继承构造函数里的属性和方法,并不会继承到原型的内容。    console.log(instance1);    instance1.colors.push('y');    console.log(instance1.colors); // ['r', 'g', 'b', 'y']    instance1.sayName(); // Nico    instance1.sayAge(); // 24    var instance2 = new SubType('azure', 23);    console.log(instance2.colors); // ['r', 'g', 'b']    instance2.sayName(); // Azure    instance2.sayAge(); // 23

欧耶~~结束~~


原创粉丝点击