[JavaScript] Object常用方法小结 for..in和Object.keys的区别

Introduction

在学习JavaScript原型链、继承等的时候常常遇到Object类型方法相关的方法,特总结如下。

Object.defineProperty

Object.defineProperty(obj, prop, descriptor)方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

Object.defineProperty(object1, 'property1', {
  configurable: true,
  enumerable: true,
  value: 42,
  writable: true
});

Object.defineProperties

Object.defineProperties(obj, props)方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。

var obj = {};
Object.defineProperties(obj, {
  'property1': {
    value: true,
    writable: true
  },
  'property2': {
    value: 'Hello',
    writable: false
  }
  // etc. etc.
});

Object.prototype.hasOwnProperty

hasOwnProperty()只在属性存在于实例中时才返回 true

prototype1  = {type: 'car'}
const prototype2 = Object.create(prototype1);
prototype2.color = 'red'
const object1 = Object.create(prototype2);
object1.color = 'blue'

console.log(object1.type); // car
console.log(object1.color); // blue

console.log(object1.hasOwnProperty('color')); // true
console.log(object1.hasOwnProperty('type')); // false

Object.create()

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。

const person = {
    isHuman: false,
    sayHello: function () { alert('hello') }
}
const women = Object.create(person)
women.gender = 'women'
women.isHuman = true
women.sayHello() // 打印hello

Object.assign

Object.assign(target, …sources)方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。它将返回目标对象。

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

const returnedTarget = Object.assign(target, source);

console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }

console.log(returnedTarget);
// expected output: Object { a: 1, b: 4, c: 5 }

Object.getOwnPropertyDescriptor

Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)

const object1 = {
  property1: 42
};

const descriptor1 = Object.getOwnPropertyDescriptor(object1, 'property1');

console.log(descriptor1);
// {value: 42, writable: true, enumerable: true, configurable: true}

Object.getPrototypeOf

Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)。

const prototype1 = {};
const object1 = Object.create(prototype1);

console.log(Object.getPrototypeOf(object1) === prototype1);
// expected output: true

Object.prototype.isPrototypeOf

isPrototypeOf() 方法用于测试一个对象是否存在于另一个对象的原型链上。

prototype1  = {}
const prototype2 = Object.create(prototype1);
const object1 = Object.create(prototype2);

console.log(prototype1.isPrototypeOf(object1)); // true
console.log(prototype2.isPrototypeOf(object1)); // true

属性值 in 对象

in 操作符会在通过对象能够访问给定属性时返回 true,无论该属性存在于实例中还是原型中。

prototype1  = {type: 'car'}
const prototype2 = Object.create(prototype1);
prototype2.color = 'red'
const object1 = Object.create(prototype2);
object1.color = 'blue'

console.log(object1.type); // car
console.log(object1.color); // blue

console.log('color' in object1); // true
console.log('type' in object1); // true

in操作符和Object.prototype.hasOwnProperty的区别

in 操作符只要通过对象能够访问到属性就返回 true,

hasOwnProperty()只在属性存在于实例中时才返回 true,

因此如果 in 操作符返回 true 而 hasOwnProperty()返回 false,就可以确定属性是原型中的属性。

// 判断属性是否是原型中的属性
function myHasProtypeProperty (obj, name) {
    return (name in obj) && !(obj.hasProperty(name))
}

for…in循环

在使用 for-in 循环时,返回的是所有能够通过对象访问的、可枚举的( enumerated)属性,其中既包括存在于实例中的属性,也包括存在于原型中的属性。屏蔽了原型中不可枚举属性(即将[[Enumerable]]标记为 false 的属性)的实例属性也会在 for-in 循环中返回,因为根据规定,所有开发人员定义的属性都是可枚举的——只有在 IE8 及更早版本中例外。

prototype1  = {type: 'car'}
const prototype2 = Object.create(prototype1);
prototype2.color = 'red'
const object1 = Object.create(prototype2);
object1.color = 'blue'
object1.toString = function () { console.log('哈哈哈') } // 屏蔽了原型中不可枚举属性的实例属性

for (key in object1) {
    console.log(key)
    // 打印 color 和 type和toString
}

Object.keys()

要取得对象上所有可枚举的实例属性,可以使用 ECMAScript 5 的 Object.keys()方法。这个方法接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组。

prototype1  = {type: 'car'}
const prototype2 = Object.create(prototype1);
prototype2.color = 'red'
const object1 = Object.create(prototype2);
object1.color = 'blue'
object1.toString = function () { console.log('哈哈哈') } // 屏蔽了原型中不可枚举属性的实例属性

console.log( Object.keys(object1) ) // ["color", "toString"]
console.log( Object.keys(prototype2) ) // ["color"]
console.log( Object.keys(prototype1) ) // ["type"]

判断一个对手是否为空对象

function checkNullObj(obj) {
  return Object.keys(obj).length === 0;
}
function checkNullobj2 (obj) {
    if (JSON.stringify(data) === '{}') {
        return false // 如果为空,返回false
    }
    return true // 如果不为空,则会执行到这一步,返回true
}

Object.getOwnProperyNames()

如果你想要得到所有实例属性,无论它是否可枚举,都可以使用 Object.getOwnPropertyNames()方法。

检测对象类型

对象的 constructor 属性最初是用来标识对象类型的。但是,提到检测对象类型,还是 instanceof 操作符要更可靠一些。

instanceof 运算符用于判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。

alert(person1 instanceof Object); //true
alert(person1 instanceof Person); //true
// 自己书写的一个instanceof类似的功能
function myinstanceof(obj, FunctionObj) {
    let prototype = FunctionObj.prototype
    let proto = Object.getPrototypeOf(obj)
    while (true) {
        if (!proto) return false
        if (proto === prototype) return true
        proto = Object.getPrototypeOf(proto)
    }
}

参考

《高级程序设计第三版》

《Object》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值