javascript-Object

  • Object
    • 关于获取对象属性的几个方法的比较
    • 属性描述符中的enumerable定义了对象的属性是否可以在 for…in 循环和 Object.keys() 中被枚举。
方法名称自身可枚举属性自身不可枚举属性原型链上可枚举属性
for…in 
Object.entries(obj)  
Object.getOwnPropertyNames 
Object.keys  
Object.values  
//for...in可获取自身可枚举属性和原型链上可枚举的属性
var obj1 = {a:1,b:2};
Object.defineProperty(obj1,'e',{
	enumrable:false
});
var obj2 = Object.create(obj1);//将obj2的__proto__指向obj1
obj2.c = 3;
Object.defineProperty(obj2,'d',{
	enumrable:false
});
for(var key in obj2){
	console.log(key);//c,a,b
}
  • Object.assign

    • 将所有源对象自身的可枚举属性从一个或者多个源对象,通过源对象的getter并调用目标对象的setter设置到目标对象,如果源对象中有重复的可枚举属性,则后来的覆盖前边的。(继承属性和不可枚举属性时不可拷贝的)
    • Object.assign(target,…sources)
    • 返回target(因为target被更改,所以如果不想使target被更改,则需要使用{}代替target,这是一种常见的assign类型)
    • Object.assign为浅拷贝
    • 异常会打断后续拷贝任务
  • Object.create()

    • 创建一个对象,使用现有对象提供新创建对象的__proto__(正常情况下,__proto__指向的是现有对象的prototype),
    • Object.create(proto,[propertiesObject])
    • proto:新创建对象的原型对象
    • propertiesObject:要添加到新创建对象的可枚举属性对象的属性描述符以及相应的属性名称。这些名称对应Object.defineProperties()的第二个参数
    • 例子
      使用Object.create(null)创建一个不继承任何父类的对象(甚至没有Object.prototype的方法,完全自定义)
var testObj = Object.create(null);
testObj.__proto__;//undefined
var testObj1 = {};
testObj1.__proto__===Object.prototype;//true

使用Object.create实现继承

function Shape(){
	this.x = 0;
	this.y = 0;
}

Shape.prototype.move = function(x,y){
	this.x += x;
	this.y += y;
}

function Rectangle() {
	//这里使用父类的构造函数,相当于Java中的super()
	Shape.call(this);
}
//到这个时候为止,Rectangle.prototype.__proto__ === Object.prototype为true
//也就是说,Rectangle继承自Object
//要想让Rectangle继承Shape,就要改变__proto__的指向
//a = Object.create(b),意思就是:使a.__proto__=b
//但是Object.create改变了Rectangle.prototype.constructor的指向,需要再次纠正过来
Rectangle.prototype = Object.create(Shape.prototype);

Rectangle.prototype.constructor = Rectangle;
  • Object.defineProperty()

    • 在一个对象上添加一个新的属性,或者修改现有属性,并返回这个对象。
    • Object.defineProperty(obj, prop, descriptor)
    • 这个方法允许修改默认的额外选项(或配置)。默认情况下,使用 Object.defineProperty() 添加的属性值是不可修改的(这里的意思是,如果使用显式的使用Object.defineProperty()设置的值是不可以修改的。之前有一个误区,以为:var obj = {a:1};这样的obj.a怎么可能是默认不可修改的!)。
    • 属性描述符:对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符数据描述符是一个具有值的属性,该值可能是可写的,也可能不是可写的。存取描述符是由getter-setter函数对描述的属性。描述符必须是这两种形式之一;不能同时是两者
      • 数据描述符和存取描述符均具有以下可选键值:
        • configurable:当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false
        • enumerable:当且仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中。默认为 false。
      • 数据描述符同时具有以下可选键值:
        • value:该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
        • writable:当且仅当该属性的writable为true时,value才能被赋值运算符改变。默认为 false。
      • 存取描述符同时具有以下可选键值:
        • get:一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)。默认为 undefined。
        • set:一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。**当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。**默认为 undefined。
      • 如果一个描述符不具有value,writable,get 和 set 任意一个关键字,那么它将被认为是一个数据描述符。如果一个描述符同时有(value或writable)和(get或set)关键字,将会产生一个异常。
      • 如果属性已经存在,Object.defineProperty()将尝试根据描述符中的值以及对象当前的配置来修改这个属性。如果旧描述符将其configurable 属性设置为false,则该属性被认为是“不可配置的”,并且没有属性可以被改变(除了单向改变 writable 为 false)。当属性不可配置时,不能在数据和访问器属性类型之间切换。
        当试图改变不可配置属性(除了writable 属性之外)的值时会抛出TypeError,除非当前值和新值相同。
      • Configurable 特性:configurable特性表示对象的属性是否可以被删除,以及除writable特性外的其他特性是否可以被修改。
  • Object.defineProperties()

    • 直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
var obj = {};
Object.defineProperties(obj, {
  'property1': {
    value: true,
    writable: true
  },
  'property2': {
    value: 'Hello',
    writable: false
  }
  // etc. etc.
});
  • Object.entries(obj)

    • 返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for…in 循环遍历该对象时返回的顺序一致(*区别在于 for-in 循环也枚举原型链中的属性)。
    • 给定对象自身可枚举属性的键值对数组。
  • Object.freeze()

    • Object.freeze可以冻结一个对象,“冻结”指的是不能向这个这个对象添加新的属性,不能删除这个对象已有的属性,不能修改已有属性的值,以及不能修改已有属性的可枚举性、可配置性、可写性。该方法返回被冻结的对象
    • 返回的是传递的对象,而不是创建一个被冻结的副本。
    • Object.freeze()是浅冻结的。
  • Object.getOwnPropertyDescriptor(obj,prop)

    • 返回对象上一个自有属性的属性描述符
    • 如果不存在该自有属性,则返回undefined
  • Object.getOwnPropertyDescriptors(obj)

    • 返回自身所有属性的描述符,如果自身没有任何属性,返回空对象。
  • Object.getOwnPropertyNames(obj)

    • 获取对象自身所有属性的属性名(包括可枚举和不可枚举的,但不包括原型链上的),返回一个数组
  • Object.getOwnPropertySymbols()

    • 返回一个给定对象自身的所有Symbol属性数组
  • Object.getPrototypeOf()

    • 返回指定对象的原型。(内部[[Prototype]]的值,我觉得就是__proto__
    • 如果没有继承属性,返回null
      示例:关于Object.getPrototypeOf(Object)
//JavaScript中的 Object 是构造函数(创建对象的包装器)。
//一般用法是:
var obj = new Object();

//所以:
Object.getPrototypeOf( Object );               // ƒ () { [native code] }
Object.getPrototypeOf( Function );             // ƒ () { [native code] }

Object.getPrototypeOf( Object ) === Function.prototype;        // true

//Object.getPrototypeOf( Object )是把Object这一构造函数看作对象,
//返回的当然是函数对象的原型,也就是 Function.prototype。

//正确的方法是,Object.prototype是构造出来的对象的原型。
var obj = new Object();
Object.prototype === Object.getPrototypeOf( obj );              // true

Object.prototype === Object.getPrototypeOf( {} );               // true
  • Object.is(val1,val2)

    • 判断两个值是否具有相同的值
    • 如果下列任何一项成立,则两个值相同:
      • 两个值都是 undefined
      • 两个值都是 null
      • 两个值都是 true 或者都是 false
      • 两个值是由相同个数的字符按照相同的顺序组成的字符串
      • 两个值指向同一个对象
      • 两个值都是数字并且
        • 都是正零 +0
        • 都是负零 -0
        • 都是 NaN
        • 都是除零和 NaN 外的其它同一个数字
      • 这种相等性判断逻辑和传统的 == 运算符所用的不同,== 运算符会对它两边的操作数做隐式类型转换(如果它们类型不同),然后才进行相等性比较,(所以才会有类似 “” == false 为 true 的现象),但 Object.is 不会做这种类型转换。
      • 这与===运算符也不一样。===运算符(和==运算符)将数字值-0和+0视为相等,并认为Number.NaN不等于NaN。
  • Object.isExtensible()

    • 判断对象是否是可扩展的(是否可以添加新的属性
    • Object.preventExtensions、Object.freeze、Object.seal都可以标记一个对象为不可扩展
  • Object.isFrozen()

    • 判断一个对象是否被冻结
    • 一个对象被冻结,指的是它不可扩展,所有属性都是不可配置的,且所有数据属性都是不可写的。
// 一个对象默认是可扩展的,所以它也是非冻结的.
Object.isFrozen({}); // === false

// 一个不可扩展的空对象同时也是一个冻结对象.
var vacuouslyFrozen = Object.preventExtensions({});
Object.isFrozen(vacuouslyFrozen) //=== true;

// 一个非空对象默认也是非冻结的.
var oneProp = { p: 42 };
Object.isFrozen(oneProp) //=== false

// 让这个对象变的不可扩展,并不意味着这个对象变成了冻结对象,
// 因为p属性仍然是可以配置的(而且可写的).
Object.preventExtensions(oneProp);
Object.isFrozen(oneProp) //=== false

// ...如果删除了这个属性,则它会成为一个冻结对象.
delete oneProp.p;
Object.isFrozen(oneProp) //=== true

// 一个不可扩展的对象,拥有一个不可写但可配置的属性,则它仍然是非冻结的.
var nonWritable = { e: "plep" };
Object.preventExtensions(nonWritable);
Object.defineProperty(nonWritable, "e", { writable: false }); // 变得不可写
Object.isFrozen(nonWritable) //=== false

// 把这个属性改为不可配置,会让这个对象成为冻结对象.
Object.defineProperty(nonWritable, "e", { configurable: false }); // 变得不可配置
Object.isFrozen(nonWritable) //=== true

// 一个不可扩展的对象,拥有一个不可配置但可写的属性,则它仍然是非冻结的.
var nonConfigurable = { release: "the kraken!" };
Object.preventExtensions(nonConfigurable);
Object.defineProperty(nonConfigurable, "release", { configurable: false });
Object.isFrozen(nonConfigurable) //=== false

// 把这个属性改为不可写,会让这个对象成为冻结对象.
Object.defineProperty(nonConfigurable, "release", { writable: false });
Object.isFrozen(nonConfigurable) //=== true

// 一个不可扩展的对象,值拥有一个访问器属性,则它仍然是非冻结的.
var accessor = { get food() { return "yum"; } };
Object.preventExtensions(accessor);
Object.isFrozen(accessor) //=== false

// ...但把这个属性改为不可配置,会让这个对象成为冻结对象.
Object.defineProperty(accessor, "food", { configurable: false });
Object.isFrozen(accessor) //=== true

// 使用Object.freeze是冻结一个对象最方便的方法.
var frozen = { 1: 81 };
Object.isFrozen(frozen) //=== false
Object.freeze(frozen);
Object.isFrozen(frozen) //=== true

// 一个冻结对象也是一个密封对象.
Object.isSealed(frozen) //=== true

// 当然,更是一个不可扩展的对象.
Object.isExtensible(frozen) //=== false
  • Object.isSealed(obj)

    • 判断一个对象是否被密封
    • 密封对象是指不可扩展的,且所有自身属性都是不可配置的且因此不可删除(但不一定是不可写)的对象
    • 密封和冻结的差别在于:冻结对象属性值不可更改,密封对象属性值是否可以更改无所谓。也就是说冻结对象一定是密封对象,但密封对象不一定是冻结对象
  • Object.keys()

    • 返回一个给定对象自身所有可枚举属性组成的数组
  • Object.preventExtensions()

    • 使给定对象不可扩展,也就是永远不能添加新的自身属性
    • 该方法使得自身属性不能新增,但是原型上的属性依然可以新增
  • Object.prototype.hasOwnProperty()

    • 自身属性中是否具有给定属性
    • 所有继承Object的对象,都会继承到hasOwnProperty方法
    • 和in的不同之处:忽略原型链上的内容
  • Object.prototype.isPrototypeOf()

    • 测试一个对象是否在另一个对象的原型链上
function Foo() {}
function Bar() {}
function Baz() {}

Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);

var baz = new Baz();

console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true

  • Object.prototype.toString()
    • 返回描述该对象的字符串
    • 默认情况下,toString被每个Object对象所继承,如果没有被覆盖,则返回"[object type]",其中type是对象的类型。
    • toString可以用来检测对象类型
var toString = Object.prototype.toString;

toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]

//Since JavaScript 1.8.5
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
  • Object.prototype.valueOf

    • 返回对象的原始值
    • object.valueOf
    • 该方法很少需要被开发者调用,当遇到时,js自己会调用
    • 每个内置的核心对象都重写了该函数
  • Object.seal(obj)

    • 封闭一个对象,阻止添加新属性并将现有属性标记为不可配置。
    • 属性值仍然可以修改
    • 不会影响从原型链上继承的属性
  • Object.setPrototypeOf(obj,prototype)

    • 设置指定对象的原型([[Prototype]])到另一个对象
    • 更改对象的[[Prototype]]在任何浏览器或者js引擎都是很慢的操作
  • Object.values()

    • 返回给定对象的自身可枚举属性值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值