Js-高级-原型链

101 阅读4分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

原型链

面向对象特性

面向对象三大特征: 封装、继承、多态

1.封装 : 把代码放入对象的方法中

2.继承 : 一个对象(子对象) 拥有 另一个对象(父对象) 所有的成员

  • js核心就是继承

3.多态 : 一个对象在不同情况下的多种状态

  • js基本不涉及

原型继承

Js的核心是继承,那么我们是怎样实现继承的

我们js其实是是通过原型实现的,具体实现方法是 父对象作为子对象构造函数的原型

 let Person = {
      name : 'hhh',
     eat(){
         console.log('想吃肉');
     }
    }
​
    function Son(name, age) {
      this.name = name;
      this.age = age;
    }
    Son.prototype = Person;
    //将儿子的原型指向父 这样父里面的内容儿子都可以访问到 
    let s1 = new Son('芒果',18);
    console.log(s1.name);
    console.log(s1);
    s1.eat();

原型链

原型链是什么?

每一个对象都有自己的原型,而原型也是对象,也有自己的原型,以此类推形成的链式结构我们称为原型链,原型链的顶端是null

对象访问原型链的原则

原型链的本质其实是js的查找机制(就近原则),如果自己没有就找原型,自己的原型没有就找原型的原型,以此类推,如果到顶端还没有的话,如果是属性就返回undefined,如果是方法就睡报错

原型链的作用

继承

instacneof运算符

instanceof(关键字): 检测构造函数原型在不在实例对象的原型链中

   let arr = [10, 20, 30];
      // arr.__proto__ -> Array.prototype -> Objct.prototype -> null
      console.log(arr instanceof Array); //true
      console.log(arr instanceof Object); //true
      console.log(arr instanceof String); //false

instanceof 和 typeof的区别

instanceof是检测构造函数原型在不在实例对象的原型链中

typeof是检测数据类型的

函数补充

arguments

arguments关键字: 获取函数所有的实参

arguments特点

  1. arguments 能处理多个参数,它是一个伪数组
  2. arguments 只能在函数内部使用,使用arguments后函数能够接受多个参数
  3. 函数使用arguments后移入这个函数,提示信息中参数位置有...表示这个函数使用了arguments

rest

arguments能够拿到所有的实参

而rest能拿到剩余的实参(没有被使用的实参)

语法 ...形参

rest得到的是一个真数组

应用:绝大部分情况下,rest可以代替arguments

  function fn(a,b,...rest){
    console.log(a,b);
      console.log(arguments);
      console.log(rest);
    }
fn(10,20,30,40,50,60,70,80);
/*
10 20
Arguments(8) [10, 20, 30, 40, 50, 60, 70, 80]
rest(6) [30, 40, 50, 60, 70, 80]
*/

默认参数

默认参数是ES6的新语法

我们在以前想要让参数具有默认值都是用的逻辑中断,但es6之后我们可以直接在形参里面赋值,相当于默认值,如果传入值就用传入的值,没有传入就用默认

//用逻辑中断的方法
  function f(a, b) {
      a = a || 1;
      b = b || 2
      console.log(a + b);
    }
    f();  //3//使用es6默认参数的新语法
    function f(a=1, b=2) {
      console.log(a + b);
    }
    f();

class类

class的使用

ES6原型新语法:class (class就是构造函数另一种写法,功能和prototype完全一致,只是写法不同)

class类函数 : 比ES5构造函数语法更加 简洁、易读

特点:

(1)class类函数 必须要使用new调用, 否则程序报错

(2)把构造函数和原型成员 写在一个大括号里面,提高阅读性

语法:

class 类函数{

//构造函数

constructor(){}

//原型方法

eat(){}

}

 class Person{
            //构造函数
            constructor(name,age){
                this.name = name
                this.age = age
            }
            //原型方法,使用cfalss可以直接将方法写在class声明的{}里面
            eat(){
                console.log('我喜欢干饭')
            }
            learn(){
                console.log('学习')
            }
        }
        //使用class类函数之后,之前学习过的prototype所有语法全部通用
        Person.prototype.type = '哺乳动物'
        //实例对象
        let p1 = new Person('mg',22)
        console.log(p1)

extends继承

extends : 原型链继承

语法 :

class 子类函数 extends 父类函数{

//子类自己的原型方法

}

底层原理 : 替换原型继承

子类型函数.prototype.proto = 父类函数.prototype

 class Person{
            //构造函数
            constructor(name,age){
                this.name = name
                this.age = age
            }
            //原型方法
            eat(){
                console.log('我喜欢干饭')
            }
            learn(){
                console.log('学习')
            }
        }
        /* 学生构造函数 */
        class Student extends Person{
            //学生的原型的方法
            play(){
                console.log('劳逸结合')
            }
        }
​
        let s1 = new Student('mg',22)
        s1.eat(); //我喜欢干饭

super

 class Person{
            //构造函数
            constructor(name,age){
                this.name = name
                this.age = age
            }
            //原型方法
            eat(){
                console.log('我喜欢干饭')
            }
            learn(){
                console.log('学习')
            }
        }
        /* 学生构造函数 */
        class Student extends Person{
            //子类自己的构造函数
            constructor(name,age,score){
                /* 继承之后,子类不允许自己写constructor.
                如果子类想要自己写constructor, 必须要先调用super()
                */
                super(name.age);// 相当于调用了父亲的构造函数   
                this.score = score;
            }
            //学生的原型的方法
            play(){
                console.log('劳逸结合')
            }
        }
​
        let s1 = new Student('mg',22)
        s1.eat(); //我喜欢干饭