not finished
一、对象Object的属性
参考《JavaScript高级程序设计》(第三版) MDN
Object属性类型分为数据类型和访问器属性
- 数据属性
- [[configurable]]:即以下这些属性能否被更改。默认true。(相当于总开关)
- [[enumerable]]:表示能否通过for-in循环。默认true
- [[writable]]:表示能否修改属性的值。默认true
- [[value]]:包含这个属性的数据值。(注意是值)。默认undefined
注:非严格模式下,赋值会被忽略。严格模式下,赋值会报错
- 构造器属性
访问器属性不包含数据值:它们包含一对getter和setter函数,它们决定了如何处理数据。在读取访问器属性时候,会调用getter函数,负责返回有效的值;在写入访问器属性时,会调用setter函数并传入新值,这个函数决定如何处理数据。有如下四个特性- [[configurable]]:总开关,默认true
- [[enumrable]]:表能否通过for-in循环返回属性不是枚举吗,默认true
- [[get]]:在读取属性时调用的函数。默认undefined
- [[set]]:在写入属性时调用的函数。默认undefined
注:访问器不能直接定义,必须使用Object.defineProperty()定义
//get和set的示例 var book = { _year: 2004, //下划线是一种常用记号,用于表示只能通过对象方法访问的属性 edition: 1 }; Object.defineProperty(book,'year',{ //而访问器year则包含了一个getter函数和setter函数。 get:function() { return this._year; }, set:function(newValue) { if (newValue > 2004) { this._year = newValue; this.edition += newVaule -2004; } } }); //这是使用访问器属性的常见方式。即设置一个属性的值会导致其他属性发生变化 set是会遍历全部属性吗?
支持ECMAScript5的Object.defineProperty这个方法的浏览器有IE9+(IE8只是部分实现)、Firefox4+、Safari5+、Opera12+和chrome。在这个方法之前,要创建访问器属性,一般都使用两个非标准的方法__defineGetter__()和__defineSetter__方法。最初是由Firefox引入的。使用这两个遗留的方法,可以像下面这样重写前面的例子:
var book = {
_year : 2004,
edition: 1
};
//定义访问器的旧有方法
book.__defineGetter__('year',function(){
return this._year;
});
book.__defineSetter__('year',function(newValue){
if (newValue > 2004) {
this._year = newValue;
this.edition += newVaule -2004;
}
});
book.year = 2005;
alert(book.edition);//2
注:在不支持Object.defineProperty()方法的浏览器中不能修改[[congigurable]]和[[enmerable]]
- ESMAscript5又定义了一个Object.definePropertries()方法。可以定义多个属性
var book = {};
Object.defineProerties(book,{
_year: {
value:2004
},
edition:{
value:1
},
year: {
get: function() {
return this._year;
},
set: funciton(){
if(newValue>2004){
this._year = newValue;
this.edition += newavalue - 2004;
}
}
}
});
以上代码在book对外定义了两个数据属性(_year和edition)和访问器属性(year)。最终的对象与上面用defineProperty()方法定义的对象相同。唯一的区别是这里的属性都是同一时间定义的。
支持Object.defineProperties()方法有IE9+、Firefox4+、Safari5+、Opera12+和Chrome
读取属性的特性
ESMASCript5的Object.getOwnPropertyDescriptor()方法,可以取得该给定属性的描述符。
参数:属性所在和对象和要读取其扫描符的属性名称。
返回值:该对象
如果是访问器属性,这个对象有congiurable、eunmerable、writable和value
var book = {};
Object.defineProerties(book,{
_year: {
value:2004
},
edition:{
value:1
},
year: {
get: function() {
return this._year;
},
set: funciton(){
if(newValue>2004){
this._year = newValue;
this.edition += newavalue - 2004;
}
}
}
});
var descriptor = Object.getOenPropertyDescriptor(book,'_year');
alert(descriptor.value);//2004
alert(descriptor.cinfigurable);//false
alert(typeof descriptor.get);//undefined
var descriptor = Object.getOwnPropertyDescriptor(book,"year");
alert(descriptor.value);//"undefined"
alert(descriptor.enumerable);//false
alert(descriptor.get);//"function"
对于数据属性_year,value等于最初的值。configurable是false,而get等于undefined。对于访问器year,value等于undefined,configurable是false,而get是一个指向getter函数的指针。
在JavaScript中,可以针对任何对象——包括DOM和BOM对象,使用Object.getOwnPropertyDescription()方法,支持这个方法的浏览器有IE9,Firefox4+,Safari5+,Opera12+和Chrome
二、Object.defineProperty()
Object.defineProperty(obj,prop,description)用于定义或修改对象的属性,并返回这个对象- obj:要定义的对象
- prop:要定义或修改的属性
- description:要定义或修改的属性描述符
- return:被传递给函数的对象
- 注:用Symbol定义的对象的key与常规的修改不同,**如何不同?**然后Object.defineProperty是定义key为Symbol的属性的方法之一
- 通过赋值操作条件的普通属性是可枚举的(for...in或Object.keys),这些属性的值可以被改变,也可删除。默认情况,使用Object.defineProperty()添加的属性值是不可修改的。
- 属性描述符
对象里目前存在的属性描述符有主要两种形式 :- 数据描述符(default):具有值的属性
- 存取描述符:由getter-setter函数对描述的属性
- 描述符必须是这两种形式之一,不能同时是两者
数据描述符和存取描述符具有以下可选键值: - configurable:该属性描述符能否被改变,默认false
- enumerable:能否枚举,默认false
数据描述符同时具有以下可选健值 - value:该属性对应的值。默认undefined
- writable:value能否被赋值运算符改变。默认false
存取描述符同时具有以下可选健值 - get:一个给属性提供getter的方法。默认undefined。当访问该属性实,执行。方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)
- set:一个给属性提供setter的方法。默认undefined。当属性值修改时,触发该方法。参数:即该属性新的参数值
//使用__proto__
var obj = {};
var descriptor = Object.create(null);//没有继承属性
//默认没有enumerable,configurable,writable
descriptor.value = 'static';
Object.defineProperty(obj,'key',descriptor);
//显示
Object.defineProperty(obj,"key",{
enmerable: false,
configurable: false,
writable: false,
value: "static"
});
//循环使用同一对象
//这怎么循环的?
function withValue(value){
var d = withValue.d||(
withVAlue.d = {
enumable: false,
writable: false,
configurable: false,
value: null
}
)
d.value = value;
return d;
}
//并且
Object.defineProperty(obj,"key",withValue("static"));
//如果freeze可用,防止代码添加或删除对象原型的相互
//(value,get,set,enumerable,writable,configurable)
(Object.freeze||Object)(Object.prototype);
- 示例
- 创建属性
var a = {};
//在对象中添加一个顺序与数据描述符的示例
Object.defineProperty(o,"a",{
value: 37,
writable: true,
enumerable: true,
configurable: true
});
//在对象中添加一个属性与存取描述符的示例
* 修改属性
* 添加多个属性和默认值
* 一般的setters和getters
* 继承属性
三、Object.prototype
- Object.properto属性表示Object的原型对象
该属性的属性特性- writable:false
- enumerable:false
- configurable:false
- 描述
几乎所有的JavaScript对象都是Object的实例。(谁不是),一个典型的对象继承了Object.prototype的属性(包括方法),尽管这些属性可能被覆盖。但有时候可能故意创建不具有典型原型链继承的对象。比如通过Object.create(null)创建的对象,或者通过Object.setPrototypeOf方法改变原型链。
改变Object原型,会通过原型链链改变所有对象;除非在原型链中进一步覆盖受这些变化影响的属性和方法。这提供了一个非常强大、但有潜在危险的机制来覆盖或扩展对象行为。
- 属性
- Object.prototype.constructor:
- Object.prototype.proto:
- Object.prototype.noSuchMethod:
- 方法
- hasOwnProperty()
- isPrototypeOf()
- propertyIsEnumerable()
- toSource()
- tolocaleString()
- toString()
- unwatch()
- valueOf()
Object构造函数的方法
-
Object.assign(target,...sources)
把...source复制到target。return target
只拷贝可枚举的属性 -
Object.create(obj)
使用现有对象来提供新创建的对象的__proto__ -
Object.entries(obj)
返回给定对象自身可枚举属性的[key,value]数组 -
Object.freeze(obj)
冻结对象:这个对象不能被修改 删除 -
Object.is(value1,value2)
有以下任一项成立,则两值相等- 两个值都是undefined|null|true|false
- 两个值都指向同一个对象
- 两个值是由相同个数的字符按照相同的顺序组成的字符串
- 两个值都是数字且:
- 都是+0|-0|NaN|
- 都是除0和NaN外的其他同一个数字
是为了解决NaN===NaN(false)等问题
==会进行类型转换,Object.is()不会 -
Object.getPrototypeOf(obj)
返回其原型的对象,若无返回null -
Object.setPrototypeOf(obj,prototype)
给obj设置一个新原型prototype(一个对象或null)