JavaScript权威指南笔记3

对象 P120

通过对象直接量,关键字new,Object.create()(ECMAScript 5)创建对象
Object.create(null)创建一个没有原型的对象;但它不会继承任何东西,包括toString()等基础方法;也就是说,它不能和+运算符一起工作
创建一个普通的空对象

var o = Object.create(Object.prototype);
/**
 * /**
 * 兼容ECMAScript 5
 * 返回一个继承自原型对象p的属性的新对象
 * @param p 要继承原型对象
 * @returns {*} 新对象
 */
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();
}

属性访问错误 P127

下列场景给对象o设置属性p失败

o中的熟悉p是只读的
o中的属性p是继承属性,并且它是只读的
o没有使用setter方法继承属性p;并且o的可扩展性是false

删除属性 P127

delete运算符只能删除自有属性,不能删除继承属性

var a = {
    p: {
        x: 1
    }
};
var b = a.p;
delete a.p;
console.log(b.x); // 1

由于已经删除的属性的引用依然存在,在某些不严谨的代码中可能造成内存泄漏
在销毁对象的时候,要遍历属性中的属性,依次删除

delete表达式删除成功或没有任何副作用(如删除不存在的属性)或delete后不是一个属性访问表达式,delete 返回true

var o = {x: 1};
delete o.x;   // 删除x;返回true
delete o.x;   // 什么也不做(x不存在); 返回true
delete o.toString; // 什么也不做(toString是继承来的); 返回true
delete o.1      // 无意义,返回true

检测属性

检测: 属性名(字符串) in 对象;

如果对象的自有属性或者继承属性包含这个属性则返回true
hasOwnProperty() 检测是否是对象的自有属性
propertyIsEnumerable() 检测自有属性并且是可枚举的

!== 判断一个属性是否为 undefined

var o = {
    x: 1
};

console.log(o.x !== undefined); //true: o中属性x
console.log(o.y !== undefined); // false: o中没有属性y
console.log(o.toString !== undefined); // true: o继承了toString属性

in!==!=

in 可以区分不存在的属性和存在但是值为undefined的属性

var o = {
    x: undefined
};

console.log(o.x !== undefined); // false: 属性存在,值为false
console.log(o.y !== undefined); // false: 属性不存在
console.log('x' in o);          // true: 属性存在
console.log('y' in o);          // false; 属性不存在

!==区分 undefinednull

// x的值不是nullundefined
if (x != null) {
}
// x的值不是 null undefined false '' 0 NaN
if (x) {
}

枚举属性

got/in遍历可枚举属性(自有属性和继承属性)
ECMAScript 5 中:

Object.keys() 返回可枚举的自有属性的名称数组
Object.getOwnPropertyNames() 返回所有自有属性的名称数组

gettersetter

定义存储器的属性使用一个或两个和属性同名的函数,使用 getset 关键字
函数体内的 this 指向这个对象
存取器属性是可以继承的

// 直角坐标系定义
var p = {
    x : 1.0,        // x和y为普通的可读写的数据属性
    y: 1.0,

    // r  是可读写的存取器属性, 有 getter 和 setter
    get r() {
        return Math.sqrt(this.x * this.x + this.y * this.y);
    },
    set r(newValue) {
        var oldValue = Math.sqrt(this.x * this.x + this.y * this.y);
        var ratio = newValue / oldValue;
        this.x *= ratio;
        this.y *= ratio;
    },

    // theat角度 是只读存取器属性, 它只有getter方法
    get theta() {
        return Math.atan2(this.y, this.x);
    }
};

属性的特性

数据属性的4个特性:

value (它的值) writable (可写性) enumerable (可枚举性) configurable (可配性)

存取器属性的4个特性:

get (读取) set(写入) enumerable (可枚举性) configurable (可配性)

Object.getOwnPropertyDescriptor() 获取某个对象特定的属性描述符
只能得到自有属性的描述符;对于继承属性和不存在的属性,返回 undefined

console.log(Object.getOwnPropertyDescriptor(p, 'r'));
/*{
    get: [Function: r],
    set: [Function: r],
    enumerable: true,
    configurable: true
}*/

console.log(Object.getOwnPropertyDescriptor({}, 'x'));  // undefined 没有这个属性
console.log(Object.getOwnPropertyDescriptor({}, 'toString')); // undefined 继承属性

Object.defineProperty() 设置属性的特性或新建属性特性
只能修改自有属性,不能修改继承属性
返回修改后的对象

var o = {};
// 添加一个不可枚举的属性x,赋值为1
Object.defineProperty(o, 'x', {
    value : 1,
    writable: true,
    enumerable: false,
    configurable: true
});

// 属性存在但是不可枚举
console.log(o.x);  //1
console.log(Object.keys(o)); // []

// 对属性x做修改,变成只读
Object.defineProperty(o, 'x', {
    writable: false
});

// 试图修改
o.x = 2; // 操作失败但是不报错; 严格模式中抛出类型错误异常
console.log(o.x);   // 1

// 属性可配置,所以可以使用defineProperty修改值
Object.defineProperty(o, 'x', {
    value: 2
});
console.log(o.x);  // 2

// 从数据属性改为存取器属性
Object.defineProperty(o, 'x', {
    get: function() {
        return 0;
    }
});
console.log(o.x); // 0

// 没有set方法
o.x = 2;
console.log(o.x); // 0

Object.defineProperties() 同时修改多个属性
返回修改后的对象

var p = Object.defineProperties({},{
    x: {
        value: 1,
        writable: true,
        enumerable: false,
        configurable: true
    },
    y: {
        value: 2,
        writable: true,
        enumerable: true,
        configurable: true
    }
});

Object.defineProperty() Object.defineProperties() 抛出类型错误异常

  1. 如果对象是不可扩展的,则可以编辑已有的自有属性,但不能给它添加新属性
  2. 如果属性是不可配置的, 则不能修改它的可配置性和可枚举性
  3. 如果存取器属性是不可配置的,则不能修改其 gettersetter 方法,也不能将它转换为数据属性
  4. 如果数据属性是不可配置的, 则不能将它转换为存取器属性
  5. 如果数据属性是不可配置的, 则不能将它的可写性从 false 设置为 true, 但是可以从 true 修改为 false
  6. 如果数据属性是不可配置的且不可写的, 则不能修改它的值;
  7. 如果数据属性是可配置的但不可写,属性的值是可以修改的(标记为可写->修改它的值->转换为不可写)

复制属性的特性

/**
 * 给Object.prototype 添加一个不可枚举的extend()方法
 * 这个方法继承自调用它的对象,将作为参数传入对象的属性一一复制
 * 除了值之外,也复制了属性的所有特性,除非在目标对象中存在同名的属性,
 * 参数对象的所有自有对象(包括不可枚举的属性)也会一一复制
 */
Object.defineProperty(Object.prototype, 'extend', {
    writable: true,
    enumerable: false, //不可枚举
    configurable: true,
    value: function(o) {   // 值就是这个函数
        // 得到所有的自由属性,包括不可枚举属性
        var names = Object.getOwnPropertyNames(o);

        for (var i = 0; i < names.length; i++) {
            // 属性存在则跳过
            if (names[i] in this) {
                continue;
            }
            // 获取o中的属性的描述符
            var desc = Object.getOwnPropertyDescriptor(0, names[i]);
            // 用它给this创建一个属性
            Object.defineProperty(this, names[i], desc);
        }
    }
});

对象的三个属性

原型属性

我们经常把 o的原型属性 直接叫做 o的原型
通过 new 创建的对象使用构造函数的 prototype 属性作为它们的原型
通过 Object.reate() 创建的对象使用第一个参数作为它们的原型
Object.getPrototypeOf() 查询原型
p.isPrototypeOf(o) 检测 p 是否是 o 的原型

类属性

表示对象的类型信息([object class])

function classof(o) {
    if (o === null) {
        return 'Null';
    }
    else if (o === undefined) {
        return 'Undefined';
    }
    return Object.prototype.toString.call(o).slice(8, -1);
}

可扩展性

Object.isExtensible() 判断是否可扩展
Object.preventExtensions() 将对象转换为不可扩展 无法再转换为可扩展
Object.seal() 将对象设置为不可扩展,将所有自有属性都设置为不可配置;即不能给这个对象添加新属性,而且它已有的属性也不能删除或配置,不过它已有的可写属性依然可以设置
Object.isSealed() 检测是否已经封闭(sealed)
Object.freeze() 冻结对象, 将对象设置为不可扩展, 将其属性设置为不可配置, 将它自有的所有数据属性设置为只读(如果对象的存取器属性具有setter方法,存取器属性将不受影响,仍可以通过给属性赋值调用)
Object.isFrozen() 检测对象是否冻结

序列化对象

ECMAScript 5 提供JSON.stringify()JSON.parse()
NaN Infinity -Infinity 序列化的结果是 null
日期对象序列化的结果是ISO格式的日期字符串
函数 RegExp Error对象 和 undefined值不能序列化和还原
JSON.stringify() 只能序列化对象的可没据的自有属性
不能序列化的在序列化的输出字符串中会将这个属性省略掉


文章若有纰漏请大家补充指正,谢谢~~

http://blog.xinshangshangxin.com SHANG殇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值