• 原型与原型链


    • 为什么要有原型的出现?
    • 所有函数都有一个特别的属性:

      • prototype : 显式原型属性

    • 所有实例对象都有一个特别的属性:

      • __proto__ : 隐式原型属性

    • 讲原型的时候,我们应该先要记住以下几个要点,这几个要点是理解原型的关键:

      1、所有的引用类型(数组、函数、对象)可以自由扩展属性(除null以外)。

      2、所有的引用类型都有一个’_ _ proto_ _'属性(也叫隐式原型,它是一个普通的对象)。

      3、所有的函数都有一个’prototype’属性(这也叫显式原型,它也是一个普通的对象)。

      4、所有引用类型,它的实例化的对象的’_ _ proto_ _'属性指向它的构造函数的’prototype’属性。

      5、当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它的’_ _ proto_ _'属性(也就是它的构造函数的’prototype’属性)中去寻找。

    • 显式原型与隐式原型的关系

      • 函数的prototype: 定义函数时被自动赋值, 值默认为{}, 即用为原型对象

      • 实例对象的__proto__: 在创建实例对象时被自动添加, 并赋值为构造函数的prototype值

      • 原型对象即为当前实例对象的父对象

    • 原型链

      • 所有的实例对象都有__proto__属性, 它指向的就是原型对象

      • 这样通过__proto__属性就形成了一个链的结构---->原型链

      • 当查找对象内部的属性/方法时, js引擎自动沿着这个原型链查找

      • 当给对象属性赋值时不会使用原型链, 而只是在当前对象中进行操作

     

     上面可以看出实例化对象ldh.__proto__指向star的原型对象,

    而star的原型对象.__proto__指向Object的原型对象,

    而object的原型对象.__proto__指向null

    ------------------------------------------------------------------------------------------------------------------------------------------------------------

    原型:
    1. 函数的prototype属性
      * 每个函数都有一个prototype属性, 它默认指向一个Object空对象(即称为: 原型对象)
      * 原型对象中有一个属性constructor, 它指向函数对象
    2. 给原型对象添加属性(一般都是方法)
      * 作用: 函数的所有实例对象自动拥有原型中的属性(方法)
    //定义构造函数
      function Fn() {   // 内部语句: var Fn = new Function() this.prototype = {}
    
      }
     // 1. 每个函数function都有一个prototype,即显式原型属性, 默认指向一个空的Object对象
      console.log(Fn.prototype)
      // 2. 每个实例对象都有一个__proto__,可称为隐式原型
      //创建实例对象
      var fn = new Fn()  // 内部语句: this.__proto__ = Fn.prototype
      console.log(fn.__proto__)
      // 3. 对象的隐式原型的值为其对应构造函数的显式原型的值
      console.log(Fn.prototype===fn.__proto__) // true

     

     原型链(所有函数的隐式原型都指向同一原型,都一样)

    1. 原型链(图解)
      * 访问一个对象的属性时,
        * 先在自身属性中查找,找到返回
        * 如果没有, 再沿着__proto__这条链向上查找, 找到返回
        * 如果最终没找到, 返回undefined
      * 别名: 隐式原型链
      * 作用: 查找对象的属性(方法)
    2. 构造函数/原型/实体对象的关系(图解)
    3. 构造函数/原型/实体对象的关系2(图解)

     

    Function、Object、普通构造函数的原型链关系

     

    图中有几个难点:

    1.Function构造函数可以用Function.__proto__来访问Function.prototype. 这是因为Function构造函数的构造函数是他本身,作为实例化对象的角色来访问,可行。

    2.任何函数都是函数,他都继承Function的所有属性和方法,而Function是内置的构造函数,也是对象,都是继承Object的所有属性和方法。

    /*
      1. 函数的显示原型指向的对象默认是空Object实例对象
       */
      console.log(Fn.prototype instanceof Object) // true
      console.log(Object.prototype instanceof Object) // false
      console.log(Function.prototype instanceof Object) // true
      /*
      2. 所有函数都是Function的实例(包含Function)
      */
      console.log(Function.__proto__===Function.prototype)
      /*
      3. Object的原型对象的隐式原型是原型链尽头
       */
      console.log(Object.prototype.__proto__) // null

    读取属性:

    1. 读取对象的属性值时: 会自动到原型链中查找
    2. 设置对象的属性值时: 不会查找原型链, 如果当前对象中没有此属性, 直接添加此属性并设置其值
    3. 方法一般定义在原型中, 属性一般通过构造函数定义在对象本身上
    function Fn() {
    
    }
    Fn.prototype.a = 'xxx'
    var fn1 = new Fn()
    console.log(fn1.a, fn1)
    
    var fn2 = new Fn()
    fn2.a = 'yyy'
    console.log(fn1.a, fn2.a, fn2)

    运行:

    穷则独善其身,达则兼济天下……
  • 相关阅读:
    centos 7 部署confluence
    在Ubuntu操作系统里安装Docker
    Python模块-pip
    微信小程序 等宽不等高瀑布流
    微信小程序 保存图片和复制文字 功能
    C# 模拟鼠标移动和点击
    使用Fiddler抓包工具更改请求的url请求参数
    C#中Request.ServerVariables详细说明及代理
    (C# webservice 获取客户端IP疑难杂症)---试过n种方法都失败,获取代理服务器,访问者客户端真实IP
    C# 命名管道中客户端访问服务器时,出现“对路径的访问被拒绝”
  • 原文地址:https://www.cnblogs.com/hmy-666/p/14430744.html
Copyright © 2020-2023  润新知