zoukankan      html  css  js  c++  java
  • JavaScript中的原型与原型链

    原型

    原型就是每一个函数天生就可以调用的属性,这些属性每一个对象都有,对象中有 constructor 属性表示构造函数本身。

    1. 作用:实例共享属性和方法;
    2. 特点:每一个实例化对象天生就可以访问类原型中的所有内容;

    就比如,所有的对象都有 toString 和 valueOf 属性,我们就不需要给每个对象一个 toString 和 valueOf。因为 JavaScript 的做法就是把 toString 和valueOf 属性放在一个对象里(暂且叫做公用属性组成的对象),然后让每一个对象的 __proto__ 存储这个「公用属性组成的对象」的地址。

    我们先来看下面这段代码:

    let obj1 = new Object()
    let obj2 = new Object()
    console.log(obj1 === obj2)    // false
    console.log(obj1.toString === obj2.toString)    // true
    

    在上面的代码中 obj1 和 obj2 是不严格相等的,因为这两个空对象的地址不同,但是他们转为 toString 之后是相等的。虽然我们并没有给这两个空对象添加 toString 属性,但是它们自带了 toString 属性,其实这里的 toString 属性就是一个原型。


    原型链

    当对象使用属性的时候,首先在自身进行查找,如果有就直接使用,如果没有就沿着 __proto__ 这条链往下查找,直到找到 Object 原型位置,有就返回相应的值,没有就返回 underfined。

    var n = new Number()
    console.log(n.__proto__ === Number.prototype)    // true
    console.log(n.__proto__.__proto__ === Object.prototype)    // true
    
    console.log(Object.prototype.__proto__ === null)    // true
    
    var 对象 = new 函数()
    
    // __proto__ 是对象的属性,prototype 是函数的属性
    对象.__proto__ === 函数.prototype
    
    // 函数的 prototype 是对象,这个对象对应的就是函数 Object
    函数.prototype.__proto__ === Object.prototype
    
    // 由于函数本身即是函数(最优先被视为函数),也是对象,而函数的构造函数是 Function
    函数.__proto__ === Function.prototype
    
    // Function 即是对象,也是函数,但他优先是个函数
    Function.__proto__ === Function.prototype
    
    // Function.prototype 也是对象,是普通的对象,所以其对应的函数是Object
    Funciton.prototype.__proto__=== Object.prototype
    

    所有函数都是由 Function 构造出来的,因此:

    // Object 是函数,是 Function 的实例
    console.log(Object.__proto__ === Function.prototype)    // true
    

    最后我们再来看看这张图:

    原型与原型链


    下面我们来使用下 class:

    class People {
      constructor(id, name) {
        this.id = id
        this.name = name
      }
      sayHi() {
        console.log("id 是 " + this.id + ",名字是 " + this.name)
      }
    }
    
    class Student extends People {
      constructor(id, name, age) {
        super(id, name)
        this.age = age
      }
      sayHi() {
        console.log("id 是 " + this.id + ",名字是 " + this.name + ",年龄是 " + this.age)
      }
    }
    
    let lq = new People(0, 'zww')
    console.log(lq)    // People {id: 0, name: "zww"}
    lq.sayHi()    // id 是 0,名字是 zww
    
    let zww = new Student(0, 'zww', 18)
    console.log(zww)    // Student {id: 0, name: "zww", age: 18}
    zww.sayHi()    // id 是 0,名字是 zww,年龄是 18
    
    // class 实际上是函数
    console.log(typeof People)    // function
    console.log(typeof Student)    // function
    
    console.log(zww.__proto__ === Student.prototype)    // true
    console.log(zww.__proto__.__proto__ === People.prototype)    // true
    
    console.log(People.__proto__ === Function.prototype)    // true
    console.log(People.__proto__ === Object.__proto__)    // true
    console.log(People.__proto__.__proto__ === Object.prototype)    // true
    
    1. 每个 class 都有显式原型 prototype;
    2. 每个实例都有隐式原型 __proto__;
    3. 实例的 __proto__ 指向对应 class 的 prototype;

  • 相关阅读:
    git创建远程分支
    npm 设置淘宝镜像的两个方法
    webpack + ts 项目的初始化
    react组件间事件触发的两种方式
    PhpStorm 使用 xdebug 进行调试(三)
    PhpStorm 使用 Apache 运行 php 代码(二)
    搭建 PHP 开发环境(Apache + PHP)(一)
    Centos7 安装 MongoDB
    Vue 中使用 vuex(十三)
    Vue 中使用 vue-router(十二)
  • 原文地址:https://www.cnblogs.com/LqZww/p/13932602.html
Copyright © 2011-2022 走看看