美文网首页
面向对象之继承

面向对象之继承

作者: 年过古稀的Coder | 来源:发表于2018-02-23 14:57 被阅读0次

内置对象

  • js提供的已经定义好的对象
  • Array,Date,Boolean,RegExp,String,Number(常用)
  • 同时js定义好了对应的一些构造函数
  • 字符串,数字等基础类型数据是没有属性和方法的
  • ??那么我们平时创建了一个字符串(非字符串对象)的时候,为什么可以调用他的length,indexOf的美好属性或方法??
  • 上面问题的答案就是:包装对象

包装对象

  • 当我们去调用字符串,数字,布尔值这三种基础数据类型的属性和方法的时候,他们本身是不具备属性和方法的,但是js内部,会自动的去调用他们对象的构造函数,然后把他们的值作为参数进行传入,然后执行对应属性或方法,并把结果进行返回
  • 包装对象一个有三个:
    string,Number,Boolean

方法

toString()

  • Object对象prototype下的一个方法
  • 所有对象都继承该方法
  • toString()自定义改写
Array.prototype.toString = function() {
        var result = 0;
        for (var i=0; i<this.length; i++) {
            result += this[i];
        }
        return result;
    }

    alert([1,2,3]);

    function Person() {

    }

//    Person.prototype = new Object();

    var p1 = new Person();
    console.log(p1);

hasOwnProperty()

  • 判断某个属性(方法)是否是某个对象自有的,就是非原型链上的
 function Person() {
        this.name = 'motao';
    }
    Person.prototype.x = 100;

    var p1 = new Person();

    console.log( p1.hasOwnProperty('name') );
    console.log( p1.hasOwnProperty('x') );

constructor

  • 属性:返回某个对象的构造函数
  • 可以重写~
    var a = [1,2,3];
//    a.constructor = 1;
    console.log(a.constructor == Array);

instanceof

  • 运算符
  • 判断一个对象是否是某个构造函数的实例化对象
var arr = [1,2,3];
    
    console.log(arr instanceof Array);

继承

function DragLimit(element) {
        // 调用Drag函数,并把Drag中this指向DragLimit的this
        Drag.call(this, element);
}
  • 如果我们是通过赋值的形式进行继承的话,那么会有问题,因为现在是对象赋值,那么DragLimit.prototype的修改会影响Drag.prototype
  • 我们可以把Drag.prototype中的属性和方法一个个的赋值给DragLimit.prototype
  • 为了方便,我们可以使用forin来批量动态的处理这些属性和方法
  • forin不只是会把Drag.prototype自身的属性循环出来,还会把一些原型链上的属性和方法也循环出来
  • 我们也可以 DragLimit.prototype = new Drag();
  • ES6的话可以更方便的解决这个问题
class DragLimit extends Drag {
    //extends 可以继承 Drag的所有,包括原型链上的
    //然后在这里可以直接修改DragLimit原型上的属性(方法),并且不会随之改掉它所继承的Drag的原型上的属性(方法);
    this.move {
        
    }
}

类式继承

直接克隆,但是如果对象下面的属性包含对象的话,传递的是地址

当改变克隆到的新对象的值得时候,也会改变原有对象的值

<script>
    /*
    * 类式继承
    * */

    function Person() {
        this.name = 'motao'
    }
    Person.prototype.eat = function() {
        console.log('eat');
    };

    function Teacher() {
        Person.call(this);
    }

    // 引用了
//    Teacher.prototype = Person.prototype;

    /**
     * 让Teacher的prototype指向Person的一个实例对象,这样的话Teacher的prototype和Person的prototype就没有直接的引用关系,但是因为Teacher的prototype是Person的一个实例,那么Teacher的prototype自动会查找Person的prototype
     *
     * 通过Teacher的prototype可以找到Person的prototype下,但是Teacher的prototype和Person的prototype又没有直接的关系
     */
    Teacher.prototype = new Person();

    var mt = new Teacher();
    console.log(mt);
    mt.eat();

//    mt.eat => mt.__proto__.eat => Teacher.prototype.eat => new Person().eat => new Person().__proto__.eat => Person.prototype.eat
</script>
graph LR
Teacher.prototype.eat-->new&nbspPerson&lt&gt.eat
new&nbspPerson&lt&gt.eat-->new&nbspPerson&lt&gt.__proto__.eat
new&nbspPerson&lt&gt.__proto__.eat-->Person.prototype.eat

原型继承

<script>
    /*
    * 和类式继承有点像
    * */

    var obj = {
        x: 100
    };

    function Foo() {}
    Foo.prototype = obj;

    var obj2 = new Foo();

    console.log(obj2.x);
</script>

深度继承

通过一个个的把原型的属性(方法)的值传给新建的一个函数extend里的newObject,并且返回,从而在深度继承的时候 var 新对象 = new extend(要继承的对象)

改变新的值得时候 不会改变原有的值

<script>
    var obj1 = {
        x: 10,
        y: 20,
        attr: {a: 1},
        arr: [1,2,3],
        z: null
    };

//    var obj2 = {};
//    for (var property in obj1) {
//        obj2[property] = obj1[property];
//    }
//    console.log(obj2);
//    obj2.x = 100;
//    console.log(obj2);
//    console.log(obj1);

    // obj2.arr 和 obj1.arr 是同一个地址
//    obj2.attr.b = 2;
//    console.log(obj2.attr);
//    console.log(obj1.attr);

    var obj2 = extend(obj1);
    console.log(obj2);
    obj2.attr.b = 2;
    console.log(obj2.attr);
    console.log(obj1.attr);

    function extend(originObject) {
        // 根据originObject的原始类型来对新对象进行对应的初始化,保证进来什么格式出去就是什么格式
        var newObject = Array.isArray(originObject) ? [] : {};
        for (var property in originObject) {
            // 如果当前数据是对象的话,那么就需要进行深度克隆
            // 注意:typeof来判断数据类型是有一个小的问题的,null的typeof结果也是object,所以需要排除null值的深度克隆
            if (typeof originObject[property] == 'object' && originObject[property] !== null) {
                // 核心:递归克隆
                newObject[property] = extend(originObject[property]);
            } else {
                newObject[property] = originObject[property];
            }

        }
        return newObject;
    }
</script>

注意

  • 如果我们尝试给字符串、数字、布尔值增加自定义的属性和方法的时候,是无效的
  • 当一个字符串被申明以后,其值就不会发生改变,除非重新覆盖,所以我们把字符串称为字符串常量

原型链

(查找c的话)
(person是me的构造函数)

me.c --> me.__proto__.c
me.__proto__.c --> me.__proto__.__proto.c

||

me.c --> person.prototype.c
person.prototype.c --> person.prototype.__proto__.c

||

me.c --> person.prototype.c
person.prototype.c --> object.prototype.c

相关文章

  • java基础-day10-面向对象4.0

    面向对象4.0 1. 面向对象之继承 1.1 生活中的继承 1.2 Java中的继承 1.3 子类对象创建,会调...

  • 【Java】面向对象:继承、组合和多态

    一. 面向对象三大特性之继承 1. 继承的概念 继承(inheritance)机制:是面向对象程序设计使代码可以复...

  • JavaScript之面向对象编程

    五、面向对象编程 目录:面向对象原型继承、面向对象class继承(ES6引入的) 1.面向对象原型继承 类:模板 ...

  • 面向对象之继承

    继承: 单继承和多继承 1.初识 class Father(object): #如果不写object默认继承 ...

  • 面向对象之继承

    内置对象 js提供的已经定义好的对象 Array,Date,Boolean,RegExp,String,Numbe...

  • 面向对象之继承

    继承 extends 关键字来继承类 被继承的类,我们称之为父类 继承后的类,我们称之为子类 子类继承父类非私有的...

  • 面向对象之继承

  • 面向对象之继承

    什么是继承 对象这种概念,本身就是十分方便的工具,我们可以通过概念将数据和功能封装到一个类中。因此可以对问题空间的...

  • 面向对象之继承

  • 面向对象之继承

    继承 继承是面向对象的又一重要特征。继承可以使用不同的类的对象具有相同的行为;为了使用其他类的方法,我们...

网友评论

      本文标题:面向对象之继承

      本文链接:https://www.haomeiwen.com/subject/aprxxftx.html