第五章

理解对象

  1. 创建对象:--->大多是直接使用字面量方式创建,可直接添加属性和方法。
  2. 属性类型:ECMAScript中有两种属性
    1. 数据属性:
      1. [[Configurable]]:表示能否通过delete删除这个属性从而重新定义属性,能否修改属性的特性或能否把属性修改为访问器属性。
      2. [[Enumerable]]:表示能否通过for-in循环返回属性。
      3. [[Writable]]:表示能否修改属性的数据值。
      4. [[Value]]:包含这个属性的数据值。读取属性的时候从这里读取;写入属性的时候从这里保存新值。默认值为undefined。
      • 对于直接使用字面量方式添加的属性,它们的[[Configurable]]、[[Enumerable]]、[[Writable]]都默认为true,[[Value]]为指定的值。
      • 要修改属性默认的特效,必须使用Object.defineProperty()方法。
        1. 该方法接收三个参数:属性所在的对象,属性的名字和一个描述符对象。该描述符对象必须是Configurable、Enumerable、Writable、Value中的一个或多个。
        2. 一旦把Configurable设置为false,即不可配置,那么就不能再把它变回为可配置的了。
        3. 在调用该方法创建一个新的属性时,如果不指定,则Configurable、Enumerable、Writable的默认值都是false。
    2. 访问器属性:不包含数据值。它们包含一对getter和setter函数(这两个函数都不是必须的)。在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值;在写入访问器属性时,会调用setter函数,这个函数负责决定如何处理数据。
      1. [[Configurable]]:表示能否通过delete删除这个属性从而重新定义属性,能否修改属性的特性或能否把属性修改为数据属性。对于直接在对象上定义的属性,这个值默认为true。
      2. [[Enumerable]]:表示能否通过for-in循环返回属性。对于直接在对象上定义的属性,这个值默认为true。
      3. [[Get]]:读取属性时调用的函数,默认值为undefined。
      4. [[Set]]:写入属性时调用的函数,默认值为undefined。
      • 访问器属性不能直接定义,必须使用Object.defineProperty()方法。
      • 不一定要同时定义出getter和setter方法。只定义getter函数则只能读取不能写入;只定义setter函数则只能写入不能读取。
    3. Object.defineProperties()方法可以同时定义多个属性。接收两个参数,第一个参数是要添加和修改属性的对象,第二个参数是要修改或添加的属性。
    4. Object.getOwnPropertyDescriptor()方法可以取得给定属性的描述符。接收两个参数:属性所在的对象和要读取其描述符的属性名字。返回一个对象。如果是访问器属性,则这个对象的属性有Configurable、Enumerable、get和set。如果是数据属性,则其属性为Configurable、Enumerable、Writable和Value。
  3. 创建对象的方法:
    1. 工厂模式
    2. 构造函数模式:会经历以下四个步骤
      1. 创建一个新的对象
      2. 将构造函数的作用域赋值给新的对象(this指向新对象)
      3. 执行构造函数中的代码
      4. 返回新对象
    3. 原型模式
      1. 每个函数都有一个prototy属性,这个属性指向一个对象,而这个对象的用途是包含由特定类型的所有实例共享的属性和方法。就是说不必在构造函数中定义对象实例的信息,而是直接将这些信息添加到原型对象中。
      2. isPrototypeOf()方法可以确定对象和原型对象之间是否是配对的。
      3. Object.getPrototypeOf()接收一个对象,可以返回该对象的原型对象。
      4. 当代码读取到某个对象的属性时,会执行搜索,目标是具有给定名字的属性。搜索首先会从对象实例本身开始。如果实例中找到了具有给定名字的属性,则返回该属性的值;如果没有找到,则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性。
      5. 当为实例对象添加属性时,这个属性就会屏蔽原型对象中保存的同名属性。可以使用delete操作符删除属性,从而重新访问原型对象中的属性。
      6. hasOwnProperty()可以检测一个属性是存在于实例中还是存在于原型中。这个方法只在给定属性存在于对象实例中时才会返回true。
      7. in操作符会在通过对象能够访问到给定属性时就返回true,无论这个属性是存在于原型还是实例中。
      8. 使用for-in循环时,返回的是所有能够通过对象访问的、可枚举的属性,其中包括存在于实例中和原型中的属性。屏蔽了原型中不可枚举属性的实例属性也会被返回。
      9. Object.keys()接收一个对象,返回该对象中所有可枚举属性组成的字符串数组。
      10. Object.getOwnPropertyName()接收一个对象,返回该对象中所有属性(可枚举和不可枚举)组成的字符串数组。
      11. 通过字面量方式来重写原型对象更加方便。但要注意,此时constructor属性中的[[Configurable]]值被设置为了true。默认下,原生的constructor属性中的[[Configurable]]值为false。
      12. 通过原生对象的原型,可以取得所有默认方法的引用,也可以重新定义新方法。可以像修改自己定义对象的原型一样修改原生对象的原型,因此可以随时添加方法。
      13. 缺点:对于原型对象中引用类型值的属性,当你修改一个实例对象中的原型对象属性时,则所有使用这个属性的实例对象都会受到影响。
    4. 组合使用构造函数模式和原型模式:构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。好处就是每个实例都有自己的一份实例属性的副本,又同时共享着对方法的引用。
    5. 寄生构造函数模式:创建一个函数,该函数用来封装创建对象的代码,然后将这个对象返回出去。使用时要加上New来创建实例对象。
    6. 稳妥构造函数模式:
      1. 稳妥对象是指没有公共属性而且其方法也不引用this的对象。
      2. 稳妥对象最适合应用于一些安全的环境中(禁止使用this和new),或者防止数据被其他应用程序改动时使用。
      3. 稳妥构造函数模式与寄生构造函数模式类型,只是有两点不同:新创建对象的实例方法不引用this;并不适用new来创建新对象。
  4. 继承
    1. 原型链:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。
    2. 所有函数的默认原型都时Object的实例。因此,默认原型都会包含一个内部指针,指向Object.prototype。
    3. 给原型添加方法的代码一定要放在替换原型的语句之后。
    4. 借用构造函数:即在构造函数内使用call()或apply()方法,将this指向所需要借用的构造函数。
    5. 组合继承:使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现实例属性的继承。这样,既可以在原型上定义方法实现了函数复用,又可以保证每个实例都有它自己的属性。
    6. 原型式继承:即将一个对象作为另一个对象的基础,然后再根据具体的需求对另一个对象进行修改。可以使用Object.create()方法来实现:接收两个参数,第一个参数是作为新对象原型的对象和为新对象定义额外属性的对象(可选)。
    7. 寄生式继承:在创建一个仅用于封装继承过程的函数,该函数在内部结合需求再对对象进行修改,最后返回这个对象。
    8. 寄生组合式继承:通过借用构造函数来来继承属性,通过原型链的混成形式来继承方法。这种方式可以避免在原型对象中创建出不必要的、多余的属性。

你可能感兴趣的:(第五章)