blog icon indicating copy to clipboard operation
blog copied to clipboard

Object

Open anjia opened this issue 6 years ago • 5 comments

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object

1. Object.keys()

返回:新的字符串数组

  • 由可枚举属性组成
  • 属性的顺序同使用for-in
const arr = ['an', 'jia', 'zora'];
console.log(Object.keys(arr));  // ["0", "1", "2"]

const obj = {
  0: 'an',
  1: 'jia',
  2: 'zora'
};
console.log(Object.keys(obj));  // ["0", "1", "2"]

const person = Object.create({}, {
  // 是不可枚举的,所以不输出
  getName: {
    value: function() { return this.name; }
  }
  
});
person.name = 'anjia';
console.log(Object.keys(person));  // ["name"]

// 基本数据类型
console.log(Object.keys('anjia'));  // ["0", "1", "2", "3", "4"]
/**
 * 说明:ES5会报错,ES2015会将非对象参数强制转换成对象
 */

anjia avatar Sep 29 '18 03:09 anjia

可枚举 vs. 不可枚举

看属性的enumerable: true|false

  • 直接赋值、属性初始化时,默认 true
  • Object.defineProperty等定义的属性,默认 false

以下方法只能取到enumerable: true的属性

  • for-in
  • Object.keys()
  • JSON.stringify()
let foo = {
  a: 1,
  b: 2
}
foo.c = 3

Object.defineProperty(foo, 'd', {
  value: 4,
  enumerable: false
})

console.log(foo.d)  // 可以获取到对象的值 4

console.log(Object.keys(foo))     // ["a", "b", "c"]
console.log(JSON.stringify(foo))  // "{\"a\":1,\"b\":2,\"c\":3}"
for(let i in foo){
  console.log(i)   // "a" "b" "c"
}

for-in 包括继承到的属性 Object.keys 仅包括对象自身

若想同时获取到可枚举属性和不可枚举属性,则可以:

console.log(Object.getOwnPropertyNames(foo))   // ["a", "b", "c", "d"]

anjia avatar Sep 29 '18 03:09 anjia

2. Object.getOwnPropertyNames()

返回:字符串数组

  • 所有自身属性的属性名
  • 包括:可枚举的、不可枚举的
  • 不包括:Symbol
  • 属性顺序
    • 可枚举属性,顺序同for-in Object.keys
    • 不可枚举属性,顺序未定义
// 数组
const arr = ['an', 'jia', 'zora'];
console.log(Object.getOwnPropertyNames(arr));  // ["0", "1", "2", "length"]

// 类数组对象
const obj = {
  0: 'an',
  1: 'jia',
  2: 'zora'
};
console.log(Object.getOwnPropertyNames(obj));  // ["0", "1", "2"]

// 包含不可枚举的
const person = Object.create({}, {
  getName: {
    value: function() { return this.name; },
    enumerable: false
  }
});
person.name = 'anjia';
console.log(Object.getOwnPropertyNames(person));  // ["getName", "name"]

// 原始对象:ES5会报错,ES2015会将非对象参数强制转换成对象
console.log(Object.getOwnPropertyNames('anjia'));   // ["0", "1", "2", "3", "4", "length"]

anjia avatar Sep 29 '18 04:09 anjia

获取属性.原型链

function Parent() {
  this.parentProp = 'parent class'
}
Parent.prototype.parentPrototypeFoo = function() {}

function Child() {
  this.prop = 'anjia'
  this.getProp = function(){
    return this.prop
  }
}
Child.prototype = new Parent;
Child.prototype.prototypeFoo = function() {}

const kid = new Child()
Object.defineProperty(kid, 'age', {
  value: 30,
  enumerable: false
})

console.log(Object.getOwnPropertyNames(kid));  // ["prop", "getProp", "age"]
console.log(Object.keys(kid)); // ["prop", "getProp"]
for(let i in kid){
  console.log(i);  // "prop" "getProp" "parentProp" "prototypeFoo" "parentPrototypeFoo"
}
  • Object.getOwnPropertyNames() 仅自身,可枚举+不可枚举
  • Object.keys() 仅自身,可枚举
  • for-in 自身+原型链,可枚举

anjia avatar Sep 29 '18 04:09 anjia

Object.getOwnPropertyDescriptor()

获取属性.详情

let foo = {
  a: 1,
  b: 2
}
foo.c = 3

Object.defineProperty(foo, 'd', {
  value: 4,
  enumerable: false
})


function getDetail(obj, prop) {
  console.log(Object.getOwnPropertyDescriptor(obj, prop))
}

getDetail(foo, 'a')
/*
{
  configurable: true,
  enumerable: true,
  value: 1,
  writable: true
}
*/


getDetail(foo, 'd')
/*
{
  configurable: false,
  enumerable: false,
  value: 4,
  writable: false
}
*/

anjia avatar Sep 29 '18 04:09 anjia

  • for-in 自身+原型链,可枚举
  • Object.keys() 自身,可枚举
  • Object.getOwnPropertyNames() 自身,可枚举+不可枚举

  • prop in obj1 自身+原型链
  • obj1.hasOwnProperty(prop) 自身
  • obj1.propertyIsEnumerable(prop) 可枚举

后三个,详见 #16

anjia avatar Sep 29 '18 07:09 anjia