zoukankan      html  css  js  c++  java
  • 前端修仙之路-五、JavaScript原型初学者指南(1)

    在JavaScript的世界中,万物皆对象。如果不处理对象,您将无法在JavaScript中走得很远。

    它们是JavaScript编程语言几乎所有方面的基础。实际上,学习如何创建对象可能是您刚开始学习时首先学习的内容之一。

    话虽如此,为了最有效地了解JavaScript原型,我们从基础知识开始。

    对象的表现形式是键/值对。创建对象的最常见方法是使用花括号{},然后使用点表示法将属性和方法添加到对象。

    let animal = {}
    animal.name = 'Leo'
    animal.energy = 10
    
    animal.eat = function (amount) {
      console.log(`${this.name} is eating.`)
      this.energy += amount
    }
    
    animal.sleep = function (length) {
      console.log(`${this.name} is sleeping.`)
      this.energy += length
    }
    
    animal.play = function (length) {
      console.log(`${this.name} is playing.`)
      this.energy -= length
    }

    一个简单animal对象就创建完成了,当然还可以继续给它添加属性和方法。

    简单来说,现在在我们的程序中,我们将需要创造不止一种动物,猫、狗、大象……。自然,下一步是将该逻辑封装在一个函数中,我们可以在需要创建新动物时调用该逻辑。我们将其称为“功能实例化”  Functional Instantiation,并将函数本身称为“构造函数”,因为它负责“构造”新对象。

    功能实例化

    function Animal (name, energy) {
      let animal = {}
      animal.name = name
      animal.energy = energy
    
      animal.eat = function (amount) {
        console.log(`${this.name} is eating.`)
        this.energy += amount
      }
    
      animal.sleep = function (length) {
        console.log(`${this.name} is sleeping.`)
        this.energy += length
      }
    
      animal.play = function (length) {
        console.log(`${this.name} is playing.`)
        this.energy -= length
      }
    
      return animal
    }
    
    const cat = Animal('Cat', 7)
    const dog = Animal('Dog', 10)

    现在,每当我们要创建一个新的动物(或者更广泛地说一个新的“实例”),我们所要做的就是调用我们的Animal函数,给它添加名字和能量。

    上面的方法简单明了,这很好用,而且非常简单。

    但是,您可以发现这种模式有什么缺点吗?

    动物都有三种方法- eat(吃饭)sleep(睡觉)play(玩)这些方法中的每一个不仅是动态的,而且是完全通用的。

    这意味着没有必要重新创建这些方法,就像我们在创建新动物时所做的那样。我们只是在浪费内存,使每个动物对象都超出其需要。

    您能想到解决方案吗?

    如果不是每次创建新动物时都重新创建这些方法,而是将它们移到它们自己的对象上,然后让每个动物都引用该对象怎么办?

    我们可以称这种模式为共享方法的功能实例化。

    共享方法的功能实例化

    const animalMethods = {
      eat(amount) {
        console.log(`${this.name} is eating.`)
        this.energy += amount
      },
      sleep(length) {
        console.log(`${this.name} is sleeping.`)
        this.energy += length
      },
      play(length) {
        console.log(`${this.name} is playing.`)
        this.energy -= length
      }
    }
    
    function Animal (name, energy) {
      let animal = {}
      animal.name = name
      animal.energy = energy
      animal.eat = animalMethods.eat
      animal.sleep = animalMethods.sleep
      animal.play = animalMethods.play
    
      return animal
    }
    
    const cat = Animal('Cat', 7)
    const dog = Animal('Dog', 10)

    通过将共享方法移动到它们自己的对象并在我们的Animal函数内部引用该对象,我们现在解决了内存浪费和过大的Animal对象的问题。

    对象创建

    让我们通过使用Object.create再次完善示例。

    简而言之,Object.create允许您创建一个对象,该对象将在失败的查找时委派给另一个对象

    换句话说,Object.create允许您创建一个对象,并且只要对该对象的属性查找失败,它就可以查询另一个对象以查看该另一个对象是否具有该属性。

    话有点多,让我们看一些代码。

    const parent = {
      name: 'Stacey',
      age: 35,
      heritage: '一千万'
    }
    
    const child = Object.create(parent)
    child.name = 'Ryan'
    child.age = 7
    
    console.log(child.name) // Ryan
    console.log(child.age) // 7
    console.log(child.heritage) // 一千万

    因此,在上面的示例中,由于child是使用创建的Object.create(parent),因此每当对属性进行失败的查找时child,JavaScript都会将查找委托给该parent对象(找到它的父类)。

    这意味着即使child没有heritage财产,就会往上查找parent(父类)child.heritage您将获得parent的遗产“一千万”

    现在,Object.create在我们的工具类中,我们如何使用它来简化Animal以前代码?

    好吧,与其像现在那样将所有共享方法一一添加到Animal,不如使用Object.create委托给animalMethods对象。

    听起来真的很聪明,我们称之为一个共享方法和Object.create的功能实例化。

    共享方法和Object.create的功能实例化

    const animalMethods = {
      eat(amount) {
        console.log(`${this.name} is eating.`)
        this.energy += amount
      },
      sleep(length) {
        console.log(`${this.name} is sleeping.`)
        this.energy += length
      },
      play(length) {
        console.log(`${this.name} is playing.`)
        this.energy -= length
      }
    }
    
    function Animal (name, energy) {
      let animal = Object.create(animalMethods)
      animal.name = name
      animal.energy = energy
    
      return animal
    }
    
    const cat = Animal('Cat', 7)
    const dog = Animal('Dog', 10)
    
    cat.eat(10)
    dog.play(5)

    因此,现在当我们调用时cat.eat,JavaScript将eat在cat对象寻找方法该查找将失败,然后由于Object.create,它将委派给将animalMethods在其中找到对象eat

    到现在为止还挺好。我们仍然可以做一些改进。似乎必须要管理一个单独的对象(animalMethods)才能在实例之间共享方法,这只是一点点笨拙 

    这似乎是您希望在语言本身中实现的一项常用功能。

    事实证明,这就是您在这里的全部原因- prototype(原型)

    那么prototype在JavaScript中到底是什么呢?

    简而言之,JavaScript中的每个函数都有一个prototype引用对象属性。不相信,对吗?自己测试一下。

    function doThing () {}
    console.log(doThing.prototype) // {}

    如果不是将单独的animalMethods每个对象放在Animal函数的原型上,而不是创建一个单独的对象来管理我们的方法(就像我们正在使用),该怎么办?

    然后,我们要做的就是代替使用Object.create委托给animalMethods,而可以使用它委托给Animal.prototype我们称这种模式Prototypal Instantiation(原型实例化)

    原型实例化

    function Animal (name, energy) {
      let animal = Object.create(Animal.prototype)
      animal.name = name
      animal.energy = energy
    
      return animal
    }
    
    Animal.prototype.eat = function (amount) {
      console.log(`${this.name} is eating.`)
      this.energy += amount
    }
    
    Animal.prototype.sleep = function (length) {
      console.log(`${this.name} is sleeping.`)
      this.energy += length
    }
    
    Animal.prototype.play = function (length) {
      console.log(`${this.name} is playing.`)
      this.energy -= length
    }
    
    const cat = Animal('Cat', 7)
    const dog = Animal('dog', 10)
    
    leo.eat(10)
    snoop.play(5)

    同样,prototype它只是JavaScript中每个函数都具有的属性,并且如我们上面所见,它允许我们在函数的所有实例之间共享方法。我们所有的功能仍然相同,但是现在不必为所有方法管理单独的对象,我们只需使用Animal函数本身内置的另一个对象即可Animal.prototype

    这篇就先讲这么多!

  • 相关阅读:
    sort和uniq去重操作【转】
    MySQL中interactive_timeout和wait_timeout的区别【转】
    Keepalived详解(五):Keepalived集群中MASTER和BACKUP角色选举策略【转】
    Keepalived详解(四):通过vrrp_script实现对集群资源的监控【转】
    Keepalived详解(三):Keepalived基础功能应用实例【转】
    Spring详解(六)------AspectJ 实现AOP
    深入理解计算机系统(1.3)------操作系统的抽象概念
    深入理解计算机系统(1.2)------存储设备
    深入理解计算机系统(1.1)------Hello World 是如何运行的
    深入理解计算机系统(序章)------谈程序员为什么要懂底层计算机结构
  • 原文地址:https://www.cnblogs.com/liao123/p/14269863.html
Copyright © 2011-2022 走看看