构造函数继承

  • 继承:子类继承父类所有属性和行为,父类不受影响。
  • 目的:找到类之间的共性精简代码

原型链

原型链是指对象在访问属性或方法时的查找方式。

1.当访问一个对象的属性或方法时,会先在对象自身上查找属性或方法是否存在,如果存在就使用对象自身的属性或方法。如果不存在就去创建对象的构造函数的原型对象中查找 ,依此类推,直到找到为止。如果到顶层对象中还找不到,则返回 undefined。

2.原型链最顶层为 Object 构造函数的 prototype 原型对象,给 Object.prototype 添加属性或方法可以被除 null 和 undefined 之外的所有数据类型对象使用。

原型的深拷贝继承

  • 传值和传址问题

    • 基本数据类型:Number、String、Boolean、Null、Undefined
    • 复杂数据类型/引用数据类型:Array、Date、Math、RegExp、Object、Function等
  • JOSN序列化的不足

    1
    如果拷贝对象包含函数,或者undefined等值,此方法就会出现问题
  • 浅拷贝和深拷贝

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //递归深拷贝
    function deepCopy(obj) {
    let newObj = Array.isArray(obj) ? [] : {};
    for (let i in obj) {
    if (obj.hasOwnProperty(i)) {
    if (typeof obj[i] === "object") {
    if (obj[i] === null) {
    newObj[i] = null;
    } else {
    newObj[i] = deepCopy(obj[i]);
    }
    } else {
    newObj[i] = obj[i];
    }
    }
    }
    return newObj;
    }

原型的继承

  • 组合继承

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    function Dad(){
    this.name = "张三";
    }
    Dad.prototype.hobby = function(){
    console.log("喜欢篮球");
    }
    function Son(height){ //有参数就传入参数,无参可省略
    Dad.call(this,height);
    // Dad.apply(this,[height])
    // Dad.bind(this)(height);
    }
    let F = function(){}
    F.prototype = Dad.prototype;
    Son.prototype = new F();
    // Son.prototype 预定义属性constructor;
    Son.prototype.constructor = Son;

    let newSon = new Son();
    newSon.hobby();
  • 深拷贝继承

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function Dad(){
    this.name = "张三";
    }
    Dad.prototype.hobby = function(){
    console.log("喜欢篮球");
    }
    function Son(height){ //有参数就传入参数,无参可省略
    Dad.call(this,height);
    // Dad.apply(this,[height])
    // Dad.bind(this)(height);
    }

    Son.prototype = deepCopy(Dad.prototype) //调用深拷贝函数
    // Son.prototype 预定义属性constructor;
    Son.prototype.constructor = Son;

    let newSon = new Son();
    newSon.hobby();

ES6中的类

  • 类的写法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Person{
    height="178cm";
    constructor(name,age){
    //属性
    this.name = name;
    this.age = age;
    }
    //方法
    getName(){
    console.log("姓名是:"+this.name);
    }
    }
    let student = new Person("张三",20);
    student.getName();
  • 静态方法和属性:实例不会继承的属性和方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Person{
    //静态方法
    static hobby(){
    console.log("喜欢篮球");
    }
    }
    //静态属性
    Person.height = "178cm";
    //通过类来调用
    Person.hobby();
    console.log(Person.height);
  • 类的继承:extends

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class Dad{
    name = "张三";
    age = 40;
    constructor(height){
    this.height = height;
    }
    hobby(){
    console.log("喜欢篮球");
    }
    }
    class Son extends Dad{
    constructor(height){
    //表示父类的构造函数
    super(height);
    }
    }
    let son1 = new Son("178cm");
    son1.hobby();
    console.log(son1.height);

包装对象

  • 除过null,undefined,基本类型都有自己对应的包装对象:String Number Boolean
  • 包装对象把所有的属性和方法给了基本类型,然后包装对象消失

常用方法

  • hasOwnProperty():看是不是对象自身底下的属性
  • contructor查看对象的构造函数 可以用来做判断
  • instanceof:对象与构造函数是否在原型链上有关系
  • toString()判断类型; 转换字符串 进制转换

利用组合继承和深拷贝继承实现的拖曳实例