美文网首页
对象的创建

对象的创建

作者: 东方三篇 | 来源:发表于2021-11-23 20:39 被阅读0次

    创建对象

    1. Object构造函数和对象字面量方法

    const person = new Object() // 构造函数方法
    person.name = 'tom'
    
    const person = { // 对象字面量方法
        name: 'tom'
    }
    

    2. 工厂模式

    工厂模式是一种众所周知的设计模式,广泛的应用在软件工程领域, 用于抽象创建特性对象的过程。
    
    function createPerson (name, age, job) {
      let o = new Object()
      o.name = name
      o.age = age
      o.job = job
      o.sayName = function () { // 不能使用 箭头 函数,this的指向会有问题
        console.log(this.name)
      }
      return o
    }
    const person = createPerson('tom', 27, 'student')
    person.sayName() // tom
    

    3. 构造函数模式(自定义)

    ECMAScript中的构造函数就是用来穿件特性类型的对象的。
    
    // function Person (name, age, job) {} 可以是函数声明式
    const Person = function (name, age, job) { // 也可以是变量表达式
      this.name = name
      this.age = age
      this.job = job
      this.sayName = function () {
        console.log(this.name)
      }
    }
    
    const person = new Person('tom', 17, 'student') // 如果不传参数,Person的括号可以不写, 只要有 new 就能正常调用
    person.sayName() // tom
    /* 
      这里使用 Person()构造函数代替了上面 createPerson() 工厂函数
      Person() 和 createPerson() 内部基本一样,只有以下区别
      1. 没有显式的创建对象
      2. 属性和方法直接赋值给this
      3. 没有 return
      4. Person 首字母大写了, 从面相对象借鉴,构造函数首字母大写,非构造函数首字母小写
    */
    

    创建 Person实例时候的 new, 构造函数执行了一下操作:

    1. 在内存中创建一个新对象
    2. 这个新对象的内部的[[Property]]特性被赋值为构造函数的 property 属性
    3. 构造函数内部的 this 被赋值为这个新对象(this指向新对象)
    4. 执行构造函数内部的代码(给新对象添加属性)
    5. 如果构造函数返回非空对象, 则返回该对象,否则返回刚创建的新对象

    上面的person对象保存着Person的实例, 所以 person 的constructor指向Person

    person.constructor === Person // true
    person instaceof Object // true
    person instaceof Person // true
    // instaceof 运算符用于检测 构造函数的 property 属性是否出现在某个实例对象的原型链上
    
    1. 构造函数也是函数
    构造函数与普通函数的区别就是调用方式的不同。任何函数只要能 new 就是构造函数, 不能 new 的函数就是普通函数
    
    // 作为构造函数
    const person = new Person('tom', 19, 'student')
    person.sayName() // tom
    
    // 作为普通函数调用
    Person('jerry', 18, 'player') // 添加到 window 对象
    window.sayName() // jerry
    // 在调用一个函数而没有明确指出 this 的情况下(即没有作为对象的方法调用,或者没有使用call()/apply()调用),this始终指向 Global 对象
    
    // 在另一个对象作用域中调用
    let o = new Object()
    Person.call(o, 'tommy', 28, 'cooker')
    // 将 o 对象指定为 Person() 内部的 this, 所以 Person()的属性和方法都会添加到 o 对象上
    o.sayName() // tommy
    

    call、apply、bind

        call和apply都是指定this指向。 apply接收两个参数:函数内this的值和一个参数数组。call与apply的不同只是参数的形式不同。call接收第一个参数this的值,后面剩下的参数是逐个传递。 两个都可以将任意对象设置为任意函数的作用域。
    
    function sum (num1, num2) {
      return num1 + num2
    }
    function callSum1 (num1, num2) {
      return sum.apply(this, arguments)
    }
    function callSum2 (num1, num2) {
      return sum.apply(this, [num1, num2])
    }
    
    console.log(callSum1(10, 10)) // 20
    console.log(callSum2(10, 10)) // 20
    
    function callSum3 (num1, num2) {
      return sum.call(this, num1, num2)
    }
    console.log(callSum3(10, 10)) // 20
    
    bind方法会创建一个新的函数实例,其this值为被绑定到传给bind()的对象
    
    window.color = 'red'
    const o = {
      color: 'blue'
    }
    function sayColor () {
      console.log(this.color)
    }
    const objSayColor = sayColor.bind(o)
    objSayColor() // blue
    
    2. 构造函数的问题
    参考 红宝书 233页 第四版
    

    4. 原型模式

    每个函数都会创建一个property属性,这个属性是一个对象, 包含应该由特定引用类型的实例共享的属性和方法。这个对象就是通过构造函数创建的对象的原型。 在property上定义的属性和方法可以被对象实例共享
    
    const Person = function () {}
    Person.prototype.name = 'tom'
    Person.prototype.age = 20
    Person.prototype.job = 'student'
    Person.prototype.sayName = function () {
      console.log(this.name)
    }
    const person1 = new Person()
    person1.sayName() // tom
    const person2 = new Person()
    console.log(person1.sayName === person2.sayName) // true 解决了构造函数每次实例化都会创建新的函数的问题
    

    相关文章

      网友评论

          本文标题:对象的创建

          本文链接:https://www.haomeiwen.com/subject/cycgtrtx.html