《JS权威指南》学习笔记(四):对象

创建对象

  1. 可以通过对象直接量或者构造函数来创建对象,此外ECMA 5还规定了一种方法
    Object.create(),第一个参数为对象的原型,第二个可选参数用来对对象的属性进行进一步描述。
    如果第一个参数传入null,则对象不继承任何东西,连最基础的例如toString()也没有,因此想创建一个普通空对象,可以传入参数Object.prototype。

  2. 为了防止代码无意间修改不受控制的对象A,可以将继承了A的对象B传入,而不是直接传入A,这样,当修改B的属性,如果修改的是原型属性,实际上是已经创建的了一个同名的实例属性,屏蔽了原型属性。防止了修改A中的属性,除非这是一个引用类型的属性。例如下面的代码:

function inherit(p) {
    if (p == null) {
        throw TypeError();
    }
    if (Object.create) {
        return Object.create(p);
    }
    var t = typeof p;
    if (t != "object" && t != "function") {
        throw TypeError();
    }
    function f() {};
    f.prototype = p;
    return new f();
}

var o = {blabla...};
func(inherit(o));

属性访问

  1. 有两种方式:. 和[]。
    前者属性名必须是确定的;而后者传入一个字符串,在运行时可以动态修改,例如当访问的属性名需要通过传入函数的参数来确定,则必须采用[]的访问方式;或者属性名是在程序运行过程中动态生成的,也需采用[]的方式。
    使用[]方式访问对象属性,实际上是把对象看作关联数组。

  2. 访问对象不存在的属性不会报错,返回undefined;但访问不存在的对象的属性则会报错,因为null和undefined是没有属性的。因此有时需要谨慎访问对象的属性,需要在访问前用if判断对象是否存在,或采用如下更简洁的方式:

var len = book && book.subtitle && book.subtitle.length;

枚举属性

  1. for in

    遍历对象中所有可枚举的属性(包括自有和继承的属性)。

  2. Object.keys()

    返回所有的可枚举的自有属性名称组成的数组。ES5提供。

  3. Object.getOwnPropertyName()

    返回所有自有属性的名称组成的数组,包括可枚举和不可枚举的。ES5提供。

删除属性

  1. delete运算符只能删除自由属性,不能删除继承的属性。且需注意一个对象是否有其他的引用, 在删除的时候可能没有删除干净。

  2. delete用于删除对象属性或数组元素,但一些内置对象的属性不能删除,此外,通过 var声明的变量和生命的function也不能删除,即便使用window.XX or this.XX的方式也不能,会什么都不做,返回false;
    但如果是以显示的方式window.XX or this.XX添加全局属性,则可直接后跟属性名进行删除:delete XX(严格模式会报错,需明确指定为对象的属性:delete this.XX)。

检测属性

  • 属性或方法名(字符串) in 对象名:检测自有或继承属性,可区分不存在的属性和存在但值为Undefined的属性;
  • o.hasOwnProperty():检测自有属性;
  • o.propertyIsEnumerable():自有且可枚举;
  • property !== undefined

存取器属性

这是ES 5中的规定,存取器属性是和属性同名的方法,不过不用function来声明,而是用get和set;当只声明了get时该属性只读不可写,当只声明set时该属性只写,读取该属性永远返回Undefined。访问存取器属性仍然使用 o.propertyName的方式。
参考:ECMAScript5中的对象存取器属性:getter和setter

属性的特性

  1. 属性的特性包括:

    • value/get
    • writable/set
    • enumerable
    • configurable
  2. 为什么要配置属性的特性重要:

    • 可给原型对象添加新方法,且将其设置为不可枚举,看起来更像内置方法;
    • 可给对象定义不能修改或删除的属性,借此“锁定”该对象。
  3. 获取对象的某个属性的特性:

    Object.getOwnPropertyDescriptor(对象,“属性名”);该方法只能获取了属性的描述符对象,能够返回自有属性的特性,要获取继承属性的特性,需要遍历原型链。

  4. 设置属性的特性:

    Object.defineProperty(对象,属性名,新的描述符对象)或Object.defineProperties同时设置多个属性的特性。
    违反规则时调用上述方法会抛出类型错误,见书P136.

对象的三个属性

  1. 原型属性

    ES 5提供了Object.getPrototypeOf()来查询对象的原型;
    o.constructor.prototype也可检测(o.construtor指向对象的构造函数);
    p.isPrototypeOf(o)用于检测p是否是o的原型对象。

  2. 类属性

    toString()方法会返回一个字符串(继承自Object.prototype),表示对象的类型信息:

  [object class]

由于很多对象继承的toString()方法被重写了,例如Array类型的数据其toString方法被重写为将数组内部的元素返回成字符串,因此需要使用下面的方式获取对象的类型:

Object.prototype.toString.call(o)

由于只需要返回的字符串的第8位到倒数第2位的字符串,因此需要对返回的字符串进行后续处理,下面的函数可以处理null和Undefined类型的数据(这两者没有toString方法):

function classOf(o) {
    if (o === null) return "Null";
    if (o === undefined) return "Undefined";
    return Object.prototype.toString.call(o).slice(8,-1);
}
  • typeOf能够区分的对象类型是:object、function,更具体的诸如Array、Date等都返回object。
  • instanceOf用于判断是哪个类的实例。

3.可扩展性

表示是否可以给对象添加新的属性。

序列化对象

  • JSON.stringify();
  • JSON.parse()

对象、数组、字符串、无穷大数字、true、false、null都可序列化和还原,NaN、Infinity、-Infinity序列化结果是null;

函数、RegExp、Error、undefined不能序列化和还原;

JSON.stringify()只能序列化可枚举的自有属性。

Object.prototype中的一些方法

  1. toString()

    在需要将对象转换为字符串的时候调用该方法,例如用 + 连接字符串和一个对象或在期望使用字符串的地方使用了对象。

    普通对象调用该方法返回 “[object object]”;
    Array、Date、Function类型的变量调用该方法会有不同的返回值。

  2. toLocaleString()

    普通对象调用该方法和调用toString没有区别,但数字、日期等类型的可以做出本地化的转换。

  3. valueOf()

    和toString很类似,但往往当JS需将对象转换为某种原始值而非字符串的时候才调用,如果在需要使用原始值的地方使用了对象JS会自动调用该方法。

其他

  1. 在期待使用对象的地方,请注意null也是一个对象。

  2. 当不能确定一个变量是否存在,如果直接使用if语句会报ReferenceError
    (访问未声明的变量),最好使用typeof,此时返回值为undefined。但当是对象的属性/方法时则直接可以用if来判断,访问不存在的属性,实际上返回了Undefined。

你可能感兴趣的:(JavaScript)