Object 对象数组
JavaScript 原生提供 Object
对象数据结构
JavaScript 的全部其余对象都继承自 Object
对象,即那些对象都是Object
的实例函数
Object
对象的原生方法分红两类:Object
对象自己的方法
Object
对象的方法Object
的实例方法
Objec
原型对象 Object.prototype
上的方法,能够被 Object 实例直接使用Object()
自己是一个函数
var obj = Object(); // 等同于 var obj = Object(undefined); var obj = Object(null); obj instanceof Object // true
instanceof
运算符用来验证,一个对象是否为指定的构造函数的实例obj instanceof Object
返回 true
,就表示 obj
对象是 Object
的实例Object
方法将其转为对应的包装对象的实例// 判断变量是否为对象的函数 function isObject(value) { return value === Object(value); } isObject([]) // true isObject(true) // false
new Object()
构造函数 的首要用途是 : 直接经过它来生成新对象。
// 经过var obj = new Object()的写法生成新对象, // 与字面量的写法var obj = {}是等价的。 // 或者说,后者只是前者的一种简便写法
// 与二者的语义是不一样的
表示将转成一个对象
则表示新生成一个对象,它的值是Object(value)new Object(value)// Object(value)value// new Object(value)value
Object.keys() 接受一个对象做为参数,返回一个数组,该数组的成员都是该对象自身的(而不是继承的)全部属性名
Object.keys()
方法 只返回可枚举的属性(详见《对象属性的描述对象》一章)Object.getOwnPropertyNames()
方法 还返回不可枚举的属性名var a = ['Hello', 'World']; Object.keys(a) // ["0", "1"] Object.getOwnPropertyNames(a) // ["0", "1", "length"] // 数组的length属性是不可枚举的属性,因此只出如今Object.getOwnPropertyNames() 方法的返回结果
var obj = { p1: 123, p2: 456 }; Object.keys(obj).length; // 2 Object.getOwnPropertyNames(obj).length; // 2
var obj = new Object(); obj.valueOf() === obj; // true
valueOf
方法,就能够获得想要的结果
var obj = new Object(); obj.valueOf = function () { return 2; }; 1 + obj // 3
// 用自定义的,覆盖obj.valueOfObject.prototype.valueOf
var o1 = new Object(); o1.toString() // "[object Object]" var o2 = {a:1}; o2.toString() // "[object Object]" 该字符串说明对象的类型。
toString
方法,可让对象在自动类型转换时,获得想要的字符串形式。
var obj = new Object(); obj.toString = function () { return 'hello'; }; obj + ' ' + 'world' // "hello world"
toString
方法,并不会返回[object Object]
,由于它们都自定义了toString
方法,覆盖原始方法
[1, 2, 3].toString() // "1,2,3" '123'.toString() // "123" (function () { return 123; }).toString(); // "function () { // return 123; // }" (new Date()).toString(); // "Tue May 10 2016 09:11:31 GMT+0800 (C
Object.prototype.toString
方法。经过函数的call
方法,能够在任意值上调用这个方法,帮助咱们判断这个值的类型
Object.prototype.toString.call(value);
typeof
运算符更准确的类型判断函数
var type = function (o){ var s = Object.prototype.toString.call(o); return s.match(/\[object (.*?)\]/)[1].toLowerCase(); }; type({}); // "object" type([]); // "array" type(5); // "number" type(null); // "null" type(); // "undefined" type(/abcd/); // "regex" type(new Date()); // "date" // 在上面这个type函数的基础上,还能够加上专门判断某种类型数据的方法 ['Null', 'Undefined', 'Object', 'Array', 'String', 'Number', 'Boolean', 'Function', 'RegExp' ].forEach(function (t) { type['is' + t] = function (o) { return type(o) === t.toLowerCase(); }; }); type.isObject({}) // true type.isNumber(NaN) // true type.isRegExp(/abc/) // true
toString
的返回结果相同,也是返回一个值的字符串形式toLocaleString
,用来返回针对某些地域的特定的值toLocaleString
方法
toString
和toLocaleString
返回值就不同,并且toLocaleString
的返回值跟用户设定的所在地域相关
属性描述对象 attributes objectui
JavaScript 提供了一个内部数据结构,用来描述对象的属性,控制它的行为,好比该属性是否可写、可遍历等等this
{
value: undefined, // 该属性的属性值,默认为undefined
writable: true, // 表示属性值(value)是否可改变(便是否可写),默认为true
enumerable: true, // 表示该属性是否可遍历,默认为true。若是设为false,会使得某些操做(好比for...in遍历对象和对象原型中能够遍历的属性、Object.keys())跳过该属性
configurable: true, // 表示可配置性,默认为true。若是设为false,将阻止某些操做改写该属性,
// 好比没法删除该属性,也不得改变该属性的属性描述对象(value属性除外)。也就是说,configurable属性控制了属性描述对象的可写性。
get: undefined, // 表示该属性的取值函数(getter),默认为undefined 每次读取该属性,都会调用这个取值函数
// 一旦定义了取值函数(或存值函数),就不能将属性设为
set: undefined // 表示该属性的存值函数(setter),默认为undefined
}
// 方式1
getsetwritabletruevar obj = Object.defineProperties({}, {
p1: { value: 1, enumerable: true },
p2: { value: 2, enumerable: false }
});
// 方式2
var obj = {name:"Tom", age:"22"};
Object.defineProperty(obj, "name", {
writable: false, // 属性不可写
enumerable: false, // 属性不可遍历 如 for in 将跳过 name 属性
configurable: false, // 属性不可配置 如 delete name
});
Object.defineProperty(obj, 'fullName', {
get:function(){
return this.name + "Michal";
},
set:function(newName){
this.name = newName.split(" ")[0];
}
});
Object.getOwnPropertyDescriptor()
方法
var obj = { p: 'a' }; // 获取obj.p的属性描述对象 Object.getOwnPropertyDescriptor(obj, 'p'); // Object {
// value: "a", // writable: true, // enumerable: true, // configurable: true // }
Object.getOwnPropertyNames()
方法
Object.defineProperty(object, propertyName, attributesObject) 方法
var obj = Object.defineProperty({}, 'p', { value: 123, writable: false, // 不可写 enumerable: true, configurable: false }); obj.p // 123 obj.p = 246; obj.p // 123
var obj = Object.defineProperties({}, { p1: { value: 123, enumerable: true }, p2: { value: 'abc', enumerable: true }, p3: { get: function () { return this.p1 + this.p2 }, // 每次读取该属性,都会调用这个取值函数 enumerable:true, configurable:true } }); obj.p1 // 123 obj.p2 // "abc" obj.p3 // "123abc"
false
var obj = {}; obj.p = 123; obj.propertyIsEnumerable('p'); // true obj.propertyIsEnumerable('toString'); // false
元属性spa
指属性描述对象的各个属性,即控制属性的属性prototype
value
属性是目标属性的值
var obj = {}; obj.p = 123; Object.getOwnPropertyDescriptor(obj, 'p').value; // 123 Object.defineProperty(obj, 'p', { value: 246 }); obj.p // 246
writable
属性,决定了目标属性的值(value)是否能够被改变
writable
为false
的属性赋值不会报错,只会默默失败'use strict'; // 采用严格模式 var obj = {}; Object.defineProperty(obj, 'a', { value: 37, writable: false }); obj.a = 37; // Uncaught TypeError: Cannot assign to read only property 'a' of object
__proto__
是原型对象,它的foo
属性不可写。obj
对象继承proto
,也不能够再自定义这个属性了。若是是严格模式,这样作还会抛出一个错误
var proto = Object.defineProperty({}, 'foo', { value: 'a', writable: false }); var obj = Object.create(proto); obj.foo = 'b'; obj.foo // 'a' 若是是严格模式,此处将抛出一个错误
var obj = Object.create(proto); Object.defineProperty(obj, 'foo', { value: 'b' }); obj.foo // "b"
enumerable
(可遍历性)返回一个布尔值,表示目标属性是否可遍历
enumerable
为false
,下面三个操做不会取到该属性for..in
循环Object.keys()
方法JSON.stringify()
方法enumerable
能够用来设置“秘密”属性obj.x
属性的enumerable
为false
,因此通常的遍历操做都没法获取该属性,使得它有点像“秘密”属性,
configurable
(可配置性)返回一个布尔值,决定了是否能够修改属性描述对象
configurable
为false
时,value
、writable
、enumerable
和configurable
都不能被修改了obj.p
的configurable设置
为false
。而后,改动value
、writable
、enumerable
、configurable
,结果都报错
writable
只有在false
改成true
会报错,true
改成false
是容许的至于value
,只要writable
和configurable
有一个为true
,就容许改动setter
,使用属性描述对象的set
属性getter
,使用属性描述对象的get
属性
var obj = Object.defineProperty({}, 'p', { get: function () { return 'getter'; }, set: function (value) { console.log('setter: ' + value); } }); obj.p // "getter" obj.p = 123 // "setter: 123"
var obj = { get p() { // 取值函数get不能接受参数 return 'getter'; }, set p(value) { // 存值函数set只能接受一个参数(即属性的值) console.log('setter: ' + value); } };
存取器每每用于,属性的值依赖对象内部数据的场合。code
var obj ={ $n : 5, get next() { return this.$n++ }, set next(n) { if (n >= this.$n){ this.$n = n; }else{ throw new Error('新的值必须大于当前值'); } } }; obj.next // 5 obj.next = 10; obj.next // 10 obj.next = 5; // Uncaught Error: 新的值必须大于当前值
var extend = function (to, from) { for (var property in from) { to[property] = from[property]; } return to; }
Object.defineProperty
方法来拷贝属性var extend = function (to, from) { for (var property in from) { if (!from.hasOwnProperty(property)){
// 来过滤掉继承的属性,不然会报错,由于读不到继承属性的属性描述对象 continue; } Object.defineProperty( to, property, Object.getOwnPropertyDescriptor(from, property) ); } return to; } extend({}, { get a(){ return 1 } }) // { get a(){ return 1 } })hasOwnPropertyObject.getOwnPropertyDescriptor
控制对象状态对象
有时须要冻结对象的读写状态,防止对象被改变
blog
JavaScript 提供了 强度依次递增的三种冻结方法是,
var obj = new Object(); Object.preventExtensions(obj); Object.defineProperty(obj, 'p', { value: 'hello' }); // TypeError: Cannot define property:p, object is not extensible. obj.p = 1; obj.p // undefined
Object.isExtensible()
方法
Object.preventExtensions
方法。var obj = new Object(); Object.isExtensible(obj); // true Object.preventExtensions(obj); Object.isExtensible(obj); // fal
Object.seal
实质是把属性描述对象的configurable
属性设为false
,所以属性描述对象再也不能改变Object.seal
只是禁止新增或删除属性,并不影响修改某个属性的值Object.isSealed
方法用于检查一个对象是否使用了Object.seal
方法
Object.isExtensible
方法返回false
Object.isFrozen()
方法用于检查一个对象是否使用了Object.freeze
方法
Object.freeze
方法之后,Object.isSealed
将会返回true
,Object.isExtensible
返回false
var obj = new Object(); Object.preventExtensions(obj); var proto = Object.getPrototypeOf(obj); proto.t = 'hello'; obj.t
// hello
obj
的原型也冻结住
var obj = new Object(); Object.preventExtensions(obj); var proto = Object.getPrototypeOf(obj); Object.preventExtensions(proto); proto.t = 'hello'; obj.t // undefined
var obj = { foo: 1, bar: ['a', 'b'] }; Object.freeze(obj); obj.bar.push('c'); obj.bar // ["a", "b", "c"]
function deepFreeze(obj){ if(typeof obj !== "object"){ return obj; }; object.freeze(obj); for(var attr in obj){ deepFreeze(obj[attr]); }; };