从一道题看Object.defineProperty(),Object.create(),for...in...用法

文章目录

        • 一、Object.defineProperty()
          • 数据描述
          • 存取器描述
        • 二、 Object.create()
        • 三、遍历对象
        • 总结

今天从一道题开始:

以下代码的输出结果是:

let o = {
    foo: 'foo'
}
let obj = Object.create(o)
Object.defineProperty(obj, 'bar', {
    value: 3
})
obj.bar = 'bar'
for(const key in obj){
    console.log(obj, key, obj[key])
}

A:1, 2
B:‘foo’
C:1
D:‘foo’, ‘bar’

一、Object.defineProperty()

语法:

Object.defineProperty(obj, prop, descriptor)

参数说明:

obj:必需。目标对象
prop:必需。需定义或修改的属性的名字
descriptor:必需。目标属性所拥有的特性

返回值:

传入函数的对象。即第一个参数obj

给对象的属性添加特性描述,目前提供两种形式:数据描述和存取器描述。

数据描述
var obj = {
    test:"hello"
}
//对象已有的属性添加特性描述
Object.defineProperty(obj,"test",{
    configurable:true | false,
    enumerable:true | false,
    value:任意类型的值,
    writable:true | false
});
//对象新添加的属性的特性描述
Object.defineProperty(obj,"newKey",{
    configurable:true | false,
    enumerable:true | false,
    value:任意类型的值,
    writable:true | false
});
  • value:属性对应的值,可以是任意类型的值,默认为undefined
  • writable:属性的值是否可以被重写。设置为true可以被重写;设置为false,不能被重写。默认为false
  • enumerable:此属性是否可以被枚举(使用for…in或Object.keys())。设置为true可以被枚举;设置为false,不能被枚举。默认为false
  • configurable:是否可以删除目标属性或是否可以再次修改属性的特性(writable, configurable,enumerable)。设置为true可以被删除或可以重新设置特性;设置为false,不能被可以被删除或不可以重新设置特性。默认为false。这个属性起到两个作用:(1)目标属性是否可以使用delete删除(2)目标属性是否可以再次设置特性

也就是说,在Object.defineProperty()内定义的属性默认不可修改不可枚举

存取器描述
var obj = {};
Object.defineProperty(obj,"newKey",{
    get:function (){} | undefined,
    set:function (value){} | undefined
    configurable: true | false
    enumerable: true | false
});
  • getter/setter:getter 是一种获得属性值的方法,setter是一种设置属性值的方法

二、 Object.create()

语法:

Object.create(obj [,propertiedObject])

参数说明:

obj:创建对象的原型,表示要继承的对象
propertiesObject:可选,也是一个对象,用于对新创建的对象进行初始化

底层实现:

    Object.create =  function (o) {
        var F = function () {};
        F.prototype = o;
        return new F();
    };

Object.create继承的应用:

    var A = function () { };
    A.prototype.sayName=function () {
        console.log('a');
    }

    // B的实例继承了A的属性
    var B = function () { };
    B.prototype = Object.create(A.prototype);
    var b = new B();
    b.sayName();  // a

三、遍历对象

总结一下遍历对象的集中方法的主要区别:

方法 可输出自身属性 可输出继承的属性 可输出不可枚举属性 可输出Symbol属性
Object.keys()
for…in…
Object.getOwnPropertyNames()
Reflect.ownKeys()

总结

归纳到这里,我们可以分析下该题。

  1. let o = {foo: 'foo'};let obj = Object.create(o),这一步可以得到obj这个实例对象的__proto__属性指向o,即obj继承了o的foo属性,属性值为foo
    在这里插入图片描述

  2. Object.defineProperty(obj, 'bar', {value: 3}),这一步执行后,obj自身包含bar属性,属性值为3,默认是不可枚举的

  3. obj.bar = 'bar',上一步中,obj内的bar属性已经默认是不可修改的了,因此这一步是无效的

  4. 到这里时,console.log(obj)
    在这里插入图片描述

  5. for(const key in obj){console.log(obj[key])},由于for…in…只能遍历出对象自身的和继承的属性,而bar属性是不可枚举的,因此只输出foo。答案为B。

你可能感兴趣的:(从一道题看Object.defineProperty(),Object.create(),for...in...用法)