JavaScript权威指南读书笔记——第六章 对象

本文深入讲解JavaScript中对象的创建方式,包括对象直接量、new关键字、Object.create()等方法,并探讨了属性的查询、设置、删除及检测机制。此外,还介绍了属性的特性、getter和setter的使用以及如何通过Object.defineProperty()进行属性特性的设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

创建对象

对象直接量

var o = {
    a : "value1",
    b : 1,
    ...
};

重点内容
通过new创建对象

var a = new Array();

Object.create()
这是一个静态函数,而不是提供给某个对象调用的方法。使用它的方法很简单,只须传入所需的原型对象即可

//  o1继承了属性x和y
var o1 = Object.create({x:1,y:2});

//  o2不继承任何属性和方法
var o2 = Object.create(null);

//  o3和new Object()一样
var o3 = Object.create(Object.prototype);

通过原型继承和创建一个新对象

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 bookName = book.name;
//  使用方括号访问对象属性
var bookPrice = book["price"];

属性的设置

//  属性设置就算没有这个属性,设置后就会添加该属性
book.name = "JavaScript";
book["price"] = 100;

属性访问错误

//  返回的是undefined,因为book没有subtitle属性
var subtitle = book.subtitle;
//  失败,在严格模式中出错
var len = book.subtitle.length;

删除属性

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

//  delete
delete book.price;

delete不能删除可配置性为false的属性

检测属性

in运算符
判断对象中是否存在属性或方法

var o = {x:1};
"x" in o;           //true
"y" in o;           //false
"toString" in o;    //true

对象的hasOwnProperty()方法用来检测给定的名字是否是对象的自有属性。对于继承属性它将返回false。

var o = {x:1};
o.hasOwnProperty("x");      //true,o中有x属性
o.hasOwnProperty("y");      //false,o中没有y属性
o.hasOwnProperty("toString");   //false,toString是继承属性

对象的propertyIsEnumerable()只检测自有属性且这个属性的可枚举性为true时才返回true。

var o = inherit({y:2});
o.x = 1;
o.propertyIsEnumerable("x");    //true:o有一个可枚举的自由属性x
o.propertyIsEnumerable("y");    //false:y是继承来的
Object.prototype.propertyIsEnumerable("toString");  //false,不可枚举

属性getter和setter

和数据属性不同,存储器属性不具有可写性。如果属性同时具有getter和setter方法,那么它是一个读/写属性。如果只有getter方法,那么它是一个只读属性。如果只有setter方法,那么它是一个只写属性,读取只写属性总是返回undefined。

var o = {
    data_prop : value,
    get accessor_prop(){...};
    set accessor_prop(value){...};
};

属性的特性

数据属性的4个特性分别是它的值(value)、可写性(writable)、可枚举性(enumerable)和可配置性(configurable)。

存储器属性的4个特性有点不同没有值(value)和可写性(writable),用了get和set来代替,这两个特性都是函数,分别代表getter方法和setter方法。

通过调用Object.getOwnPropertyDescriptor() 可以获取某个对象的特定特定属性的属性描述符。

//  返回{value:1,writable:true,enumerable:true,configurable:true}
Object.getOwnPropertyDescriptor({x:1},"x");
//  返回{set:/*func*/,set:*func*/.enumerable:true,configurable:true}
Object.getOwnPropertyDescriptor({
    get r(){...},
    set r(value){...}
},"r");

要想设置属性的特性,或者让新建属性具有某种特性,则需要调用Object.defineProperty()。

//  添加一个不可枚举的数据属性x,并赋值为1
Object.defineProperty(o, "x", {value:1, writable:true, configurable:true, enumerable:fale});

//  现在对属性x做修改,让它变为只读
Object.defineProperty(o,"x",{writable:false});

传入Object.defineProperty()的属性描述符对象不必包含4个特性。对于新创建的属性来说,默认的特性值是false或undefined。对于修改的已有属性来说,默认的特性没有做任何修改。不能修改继承属性。

如果要同时修改或创建多个属性,则需要使用Object.defineProperties()。第一个参数是要修改的对象,第二个参数是一个映射表,它包含要新建或修改的属性的名称,以及它们的属性描述符,例如:

var p = Object.defineProperties({},{
    x : {value:1, writable:true,enumerable:true,configurable:true},
    r : {
        get : function(){...},
        enumerable:true,
        configurable:true
    }
});

对象的三个属性

  • 原型属性
  • 类属性
  • 可扩展性

原型属性

对象的原型属性是用来继承属性的。
通过对象直接量创建的对象使用Object.prototype作为它们的原型。通过new创建的对象使用构造函数的prototype属性作为它们的原型。通过Object.create()创建的对象使用第一个参数作为它们的原型。

对象使用isPrototypeOf()方法来查看对象是不是该参数的原型

var p = {x:1};
var o = Object.create(p);
p.isPrototypeOf(o);                 //  true
Object.prototype.isPrototypeOf(o);  //  true

类属性

对象的类属性是一个字符串,用以表示对象的类型信息。ECMAScript 3和ECMAScript 5都为提供这个属性 设置这个属性的方法,并只有一种间接的方法可以查询它。默认的toString()方法(继承自Object.prototype)返回了如下这种格式的字符串:

[object class]

想要获取对象的类,可以调用对象的classof()方法,然后提取已返回字符串的第8个到倒数第二个位置位置的字符。

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

可扩展性

对象的可扩展性用以表示是否可以给对象添加新属性。所有内置对象和自定义对象都是显示可扩展的。

可以将对象传入Object.isExtensible(),来判断对象是否是可扩展的。如果想将对象转换为不可扩展的,需要调用Object. preventExtensible(),将待转换的对象作为参数传进去。注意,不可扩展对象不能转换为可扩展对象。preventExtensions()只影响到对象本身的扩展性。可以给不可扩展对象的原型添加属性,这个不可扩展对象同样会继承这些新属性。

Object.seal()和Object.preventExtensions()类似,除了将对象设置为不可扩展的,还将对象的所有自有属性都设置为不可配置的。

Object.freeze()将对象设置为不可扩展的,将对象的所有自有属性都设置为不可配置的,还将它自有的数据属性设置为只读。使用OBject.isFreeze()来检测对象是否冻结。

序列化

o = {x:1,y:2};
s = JSON.stringify(o);      //  序列化,s是'{x:1,y:2}'
p = JSON.parse(s);          //  反序列化

对象方法

toString()方法

tolocaleString()方法

toJSON()方法

Object.prototype实际上没有定义 toJSON()方法,但对于需要只想序列化的对象来说,JSON.stringify()方法会调用toJSON方法。如果待序列化的对象存在该方法,该方法的返回值就是序列化的结果。

valueOf()方法

当JavaScript需要将对象转换为某种原始值而非字符串才会调用它。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值