《JavaScript程序设计》—— 规范对象 Object

Object

须要链接:

MDN —— Object

JavaScript规范参考教程(Object对象)——阮一峰

规范组织器函数Object多是JavaScript最重要的对象之一,只管我们历来不会直接挪用它。每当运用一个对象直接量时,都邑隐式挪用它:

    var a = {};                // 等同于var a = new Object()
    var b = {x:1,y:2};        // 等同于var b = new Object({x:1,y:2});

组织函数定义了数据范例,所以表达式var a = new Object()表明两件事变:a是Object的一个实例,而a的原型是Object.prototype。我们用对象字面量建立的每一个对象都邑取得由Object.prototype定义的行动

《《JavaScript程序设计》—— 规范对象 Object》

以下将议论几个经常使用的重要的属性要领

1. Object()

    // 起首,将Object作为组织函数挪用和对象字面量直接定义是等价的
    var o = {};
    var o2 = new Object();
    // 注重这里所说的等价不是指相称,是指其本身和原型继续雷同
    
    // 固然也可以
    var a = {};
    var a2 = new Object(a);
    console.log(a===a2);            // true

Object本身作为东西要领

    // 返回一个Object组织器实例
    var obj = Object();
    console.log(obj instanceof Object);            // true
    
    // 返回一个字符串组织器实例
    var str = Object("string");
    console.log(str instanceof Object);            // true     等价    new String("string")
    
    // 返回一个数字组织器实例
    var num = Object(123);
    console.log(num instanceof Object);            // true        等价    new Number(123)
    
    // 返回一个布尔组织器实例
    var boo = Object(true);                        // 等价    new Boolean(true)
    var boo2 = Object(false);                    
    console.log(boo instanceof Object && boo2 instanceof Object);    // true
    
    // null存在的意义在于对象援用当中,null值最初寄义为:没有援用任何对象
    // null型只能取null一个值,null值是一个字面量,然则对null举行typeof结果为对象
    console.log(typeof null);                            // object
    console.log(Object(null) instanceof Object);        // true
    // 对null挪用Object要领,返回一个空对象
    
    
    // undefined型也只能取undefined一个值,对undefined举行typeof ,值为undefined
    console.log(typeof undefined);                        // undefined
    console.log(Object(undefined) instanceof Object);    // true
    // 也是返回一个空对象

Object本身看成东西要领运用时,可以将恣意值转为对象。这个要领经常使用于保证某个值一定是对象。假如参数是原始范例的值,Object要领返回对应的包装对象的实例

Object()传入参数为基本范例值,则返回值为其范例的组织函数的实例。

上面讨论的是基本范例值,那假如是援用范例值呢?

    var arr = [1,2,3];        
    console.log(Object(arr));            // 把原对象返回了
    console.log(Object(arr)===arr);        // true
    
    var fn = function () {};            // 把原函数返回了
    console.log(Object(fn));            // function () {}
    console.log(Object(fn)===fn);        // true
    
    var obj = {x:"obj.x"};
    console.log(Object(obj));            // [object Object]
    console.log(Object(obj)===obj);        // true
    
    // 一个推断是不是是对象的函数
    function judgeObj(obj) {
        return Object(obj)===obj? true : false;
    }
    
    console.log(judgeObj([]));            // true
    console.log(judgeObj(true));        // false
    console.log(judgeObj({}));            // true
    console.log(judgeObj(123));            // false

Object()传入的参数是援用范例值,则会返回原对象;

2. Object.keys(obj)

Object.keys() 要领会返回一个由一个给定对象的本身可罗列属性构成的数组,数组中属性名的分列递次和运用 for...in 轮回遍历该对象时返回的递次一致 (二者的重要区别是 一个 for-in 轮回还会罗列其原型链上的属性)。

Enumerable前提限定,且不可罗列原型链中的属性

    // 没法罗列到原型链中的属性
    var obj = Object.create({y:20});
    obj.x = 10;
    console.log(Object.keys(obj));        // "x"
    
    // 没法罗列Enumerable为false属性
    Object.defineProperty(obj,"z",{
        value:"z",
        enumerable:false
    })
    console.log(Object.keys(obj));        // "x"
        
    // 关于数组对象
    var arr = ["a","b","c"];
    console.log(Object.keys(arr));        // "0,1,2"
    
    // 关于随机分列的数组对象
    var obj_ramdom = {100:"a",2:"b",50:"c"};
    console.log(Object.keys(obj_ramdom));        // "2,50,100"

细致申明:MDN —— Object.keys()

3. Object.getOwnPropertyNames(obj)

Object.getOwnPropertyNames 返回一个数组,该数组对元素是 obj 本身具有的罗列或不可罗列属性称号字符串。 数组中罗列属性的递次与经由过程 for...in 轮回(或 Object.keys)迭代该对象属性时一致。 数组中不可罗列属性的递次未定义。

不受Enumerable前提限定,但不可罗列原型链中属性

假如你只需猎取到可罗列属性,检察 Object.keys 或用 for...in轮回(还会猎取到原型链上的可罗列属性,不过可以运用hasOwnProperty()要领过滤掉)。

    // 没法罗列到原型链中的属性
    var obj = Object.create({y:20});
    obj.x = 10;
    console.log(
        Object.getOwnPropertyNames(obj)
    );                                    // "x"
    
    // 可以罗列Enumerable为false的属性
    Object.defineProperty(obj,"z",{
        value:"z",
        enumerable:false
    })
    console.log(
        Object.getOwnPropertyNames(obj)
    );                                    // "x,z"
        
    // 关于数组对象(length属性为不可罗列)
    var arr = ["a","b","c"];
    console.log(
        Object.getOwnPropertyNames(arr)
    );                                    // "0,1,2,length"
    
    // 关于随机分列的数组对象
    var obj_ramdom = {100:"a",2:"b",50:"c"};
    console.log(
        Object.getOwnPropertyNames(obj_ramdom)
    );                                    // "2,50,100"

细致:MDN —— Object.getOwnPropertyNames()

for-inObject.keysObject.getOwnPropertyNames特性辨别

三者关于是不是受Enumerable的限定测试

    
    var obj = {x:10,y:20};
    Object.defineProperty(obj,"z",{
        value:30,
        enumerable:false,
    });
    
    // for-in
    for (var a in obj) {
        console.log(a);                     // "x,y"
    }
    
    // Object.keys
    console.log(
        Object.keys(obj)                    // "x,y"
    );
    
    // Object.getOwnPropertyNames()
    console.log(
        Object.getOwnPropertyNames(obj)     // "x,y,z"
    );

三者关于是不是可以罗列原型链的测试


    function Test() {
        this.x = 10;
        this.y = 20;
    }
    Test.prototype.z = 30;        // z为原型链属性
    var obj = new Test();
    
    
    // for-in
    for (var a in obj) {
        console.log(a)                         // "x,y,z"
    }
    
    // Object-keys
    console.log(
        Object.keys(obj)                       // "x,y"
    )

    
    // Object.getOwnPropertyNames()
    console.log(
        Object.getOwnPropertyNames(obj)        // "x,y"
    )

《《JavaScript程序设计》—— 规范对象 Object》

我们怎样影象呢?就记最特别的!

for-in:只要它可以罗列原型链里的属性,而且它也不是Object对象的要领

Object.getOwnPropertyNames():只要它可以享有Enumerable的”豁免权”,不论怎样设置只需是这个对象上的自有属性都可以罗列到!

对象属性掌握相干要领

四个相干的要领在这里先列出,这里要要提到数据属性和接见器属性

4. Object.defineProperty()

Object.defineProperty() 要领会直接在一个对象上定义一个新属性,或许修正一个对象的现有属性, 并返回这个对象。

5. Object.getOwnPropertyDescriptor()

Object.getOwnPropertyDescriptor() 返回指定对象上一个自有属性对应的属性形貌符。(自有属性指的是直接给予该对象的属性,不须要从原型链上举行查找的属性)

    // 采纳Object.defineProperty定义的属性,假如不显现定义
    // enumerable,configurable,writable值默认为false(与对象字面量相反)
    var obj = {};
    Object.defineProperty(obj,"x",{
        value:"obj.x"
    });
    
    
    // 运用Object.getOwnPropertyDescriptor()猎取属性对象
    var obj_attr = Object.getOwnPropertyDescriptor(obj,"x");
    for (var i in obj_attr) {
        document.write(i+" : "+obj_attr[i]+"<br />")
    }
    // 默许下数据属性都是false

6. Object.defineProperties()

Object.defineProperties() 要领直接在一个对象上定义新的属性或修正现有属性,并返回该对象。

    var obj = {};
    Object.defineProperties(obj,{
        x:{
            value:"obj.x",
            writable:true,
            enumerable:true,
            configurable:true
        },
        y:{
            value:"obj.y",
            writable:true,
            enumerable:true,
            configurable:true
        },
        z:{
            value:"obj.z"
        }
    })
    
    console.log(Object.keys(obj));            // "x,y"    z属性enumerable默认为false
    // 固然,z属性的数据属性都是false

争执:

《JavaScript编程全解》:只需将get属性与set属性指定为响应的函数,就可以定义一个只可以经由过程接见器gettersetter来接见值的属性。接见器与value属性是相互排挤的,也就是说,假如指定了value属性的值,接见器(包含getset)就会失效;反之,假如指定了接见器(getset中的某一个亦或是都存在),value属性就会失效。

《JS高程3》:不一定非要同时指定getter和setter。只指定getter意味着属性是不能写,尝试写入属性会被疏忽。在严厉情势下,尝试写入只指定了getter函数的的属性会抛出毛病。类似地,没有指定setter函数的属性也不能读,否则在非严厉情势下会返回undefined,在严厉情势下会抛出毛病。

    var obj = {_x:10};
    
    // 定义一个接见器属性
    Object.defineProperty(obj,"x",{
        get:function () {
            return this._x
        }
    })
    // 读取obj.x会隐式挪用接见器属性,返回obj._x的值(下划线代表此属性只能经由过程接见器读写)
    console.log(obj.x);            // 10
    
    // 尝试为接见器属性赋值
    // 直接赋值
    obj.x = "aaa";
    console.log(obj.x);            // 10     赋值失利
    
    // 猎取obj.x的attributes
    var objxAttr = Object.getOwnPropertyDescriptor(obj,"x");
    for (var i in objxAttr) {
        document.write(
            i+" | "+objxAttr[i]+"<br />"
        )
    }
    // get | function () { return this._x }
    // set | undefined
    // enumerable | false
    // configurable | false
    
    // 不可写的原因是value属性与接见器属性争执,即(get、set)与value属性争执
    
    // 可以经由过程检察attributes属性,推断属性是不是是接见器属性照样数据属性,存在set或许get的是接见器属性

具体内容请移步至相干知识点举行更深入进修,这里只引见要领基本用法

对象状况相干要领

Object.preventExtensions()

假如一个对象可以增加新的属性,则这个对象是可扩大的。preventExtensions 可以让这个对象变的不可扩大,也就是不能再有新的属性。须要注重的是不可扩大的对象的属性一般照旧可以被删除。尝试给一个不可扩大对象增加新属性的操纵将会失利,不过多是寂静失利,也可能会抛出 TypeError 非常(严厉情势)。

Object.preventExtensions 只能阻挠一个对象不能再增加新的本身属性,照旧可认为该对象的原型增加属性。但是Object.preventExtensions会阻挠一个对象将__proto__属性从新指向另一个对象。

    // Object.preventExtensions将原对象变的不可扩大,而且返回原对象
    var obj = {};
    var obj2 = Object.preventExtensions(obj);
    alert(obj===obj2);            // true
    obj.x = "obj.x";
    alert(obj.x);                // undefined
    
    // 采纳对象字面量定义的对象默许可扩大
    var o = {};
    alert(Object.isExtensible(o));            // true
    // 固然,经由过程挪用要领可以阻挠
    Object.preventExtensions(o);
    alert(Object.isExtensible(o));            // false
    
    // 运用Object.defineProperty要领为一个不可扩大的对象增加新属性会抛出非常.
    var o2 = {a:"a"};
    Object.preventExtensions(o2);
    Object.defineProperty(o2,"b",{
        value:"test"            
    })
    // "Uncaught TypeError: Cannot define property:b, object is not extensible."
    
    
    // 一个不可扩大对象的原型是不可变动的,__proto__是个非规范魔法属性,可以变动一个对象的原型.
    var b = Object.preventExtensions({x:1,y:2});
    b.__proto__ = {a:10,b:20};            //  "Uncaught TypeError: #<Object> is not extensible" 

细致:MDN —— Object.preventExtensions()

Object.seal()

一般状况下,一个对象是可扩大的(可以增加新的属性)。密封一个对象会让这个对象变的不能增加新属性,且一切已有属性会变的不可设置。属性不可设置的结果就是属性变的不可删除,以及一个数据属性不能被从新定义成为接见器属性,或许反之。但属性的值照旧可以修正。尝试删除一个密封对象的属性或许将某个密封对象的属性从数据属性转换成接见器属性,结果会寂静失利或抛出TypeError 非常(严厉情势)。

不会影响从原型链上继续的属性。但 _proto_ ( ) 属性的值也会不能修正。

    // 默许可以修正属性,增加属性
    var obj = {
        a:"a",
        b:"b"
    };
    
    // 密封对象Object.seal(),注重要领会返回原对象
    obj = Object.seal(obj);
    console.log(Object.isSealed(obj));            // true
    
    // 照旧可以修正属性上的值
    obj.a = "Rewrite obj.a";
    obj.b = "Rewrite obj.b";
    console.log(obj.a+" | "+obj.b);                //  "Rewrite obj.a | Rewrite obj.b"
    
    // 然则除此之外的操纵都没法完成
    obj.z = "obj.z";
    console.log(obj.z);                            // undefined 新属性写入失利
    console.log(delete obj.a);                    // false 删除失利
    
    // 没法定义接见器属性
    Object.defineProperty(obj,"b",{                // "Uncaught TypeError: Cannot redefine property: b"
        get:function () {
            return this.b;
        }
    });
    // 要领也没法写入新属性
    Object.defineProperty(obj,"z",{                // 抛出TypeError非常
        value:"obj.z"
    });
    console.log(obj.z);        // "Uncaught TypeError: Cannot define property:z, object is not extensible."

Object.freeze()

Object.freeze() 要领可以凝结一个对象,凝结指的是不能向这个对象增加新的属性,不能修正其已有属性的值,不能删除已有属性,以及不能修正该对象已有属性的可罗列性、可设置性、可写性。也就是说,这个对象永远是不可变的。该要领返回被凝结的对象。

    // 默许可以修正属性,增加属性,删除属性等操纵
    var obj = {
        a:"a",
        b:"b",
        o:{}
    };
    
    // 挪用Object.freeze
    obj = Object.freeze(obj);
    
    // 如今任何对对象的操纵都邑失利,严厉情势下会TypeError非常
    console.log(delete obj.a);                // false
    
    obj.z = "obj.z";
    console.log(obj.z);                        // undefined
    
    // 然则非凝结对象照旧可以修正,对象内数组、对象等援用范例
    obj.o.fn = function () {console.log("yes")};
    obj.o.fn();                                // "yes"    增加胜利

MDN供应了一个完整凝结对象的函数:

    obj = {
      internal : {}
    };
    
    Object.freeze(obj);
    obj.internal.a = "aValue";
    
    obj.internal.a // "aValue"
    
    // 想让一个对象变的完整凝结,凝结一切对象中的对象,我们可以运用下面的函数.
    
    function deepFreeze (o) {
      var prop, propKey;
      Object.freeze(o); // 起首凝结第一层对象.
      for (propKey in o) {
        prop = o[propKey];        
        if (!o.hasOwnProperty(propKey) || !(typeof prop === "object") || Object.isFrozen(prop)) {
        // 跳过原型链上的属性和已凝结的对象.
          continue;
        }
    
        deepFreeze(prop); //递归挪用.
      }
    }
    
    obj2 = {
      internal : {}
    };
    
    deepFreeze(obj2);
    obj2.internal.a = "anotherValue";
    obj2.internal.a; // undefined

Object.isExtensible()、Object.isSealed()、Object.isFrozen()

为对应的检测要领:

严厉水平升序:preventExtensions —— seal —— freeze

《《JavaScript程序设计》—— 规范对象 Object》

链接:

  • Object.isExtensible():

默许状况下,对象是可扩大的:即可认为他们增加新的属性。以及它们的 proto 属性可以被变动。Object.preventExtensions,Object.seal 或 Object.freeze 要领都可以标记一个对象为不可扩大(non-extensible)。

  • Object.isSealed()

    // 新建对象默许不可密封
    var obj = {};
    console.log(Object.isSealed(obj));            // false
    
    // 假如是空对象变成不可扩大preventExtensions,则对象也会变成密封对象
    obj = Object.preventExtensions(obj);
    console.log(
        Object.isExtensible(obj)+" | " +Object.isSealed(obj)
    )                                            // false | true        不可扩大  | 密封
    
    // 但不是空对象,则不会发作上面状况,记着:密封对象与Configurable属性相干联
    var obj2 = {x:"obj2.x"};
    Object.preventExtensions(obj2);
    console.log(
        Object.isExtensible(obj2)+" | " +Object.isSealed(obj2)
    )                                            // false | false    不可扩大  | 不密封
    
    // 反过来设置configurable设置为false,则自动变成密封对象
    var o = {a:"o.a"};
    Object.preventExtensions(o);
    Object.defineProperty(o,"a",{
        configurable:false
    });
    console.log(
        Object.isSealed(o)
    );                                            // true
    
    // 直接天生一个密封对象
    var obj_seal = {};
    Object.seal(obj_seal);
    
    // 固然密封对象也可所以凝结对象
    Object.isFrozen(obj_seal);                    // true
    var o2 = Object.seal({a:"o2.a"});
    console.log(Object.isFrozen(o2));            // false    照旧可变动o2.a属性
  • Object.isFrozen()

一个对象是凝结的(frozen)是指它不可扩大,一切属性都是不可设置的(non-configurable),且一切数据属性(data properties)都是不可写的(non-writable)

    // 一个对象默许是可扩大的,所以它也黑白凝结的.
    assert(Object.isFrozen({}) === false);
    
    // 一个不可扩大的空对象同时也是一个凝结对象.
    var vacuouslyFrozen = Object.preventExtensions({});
    assert(Object.isFrozen(vacuouslyFrozen) === true);
    
    // 一个非空对象默许也黑白凝结的.
    var oneProp = { p: 42 };
    assert(Object.isFrozen(oneProp) === false);
    
    // 让这个对象变的不可扩大,并不意味着这个对象变成了凝结对象,
    // 由于p属性照旧是可以设置的(而且可写的).
    Object.preventExtensions(oneProp);
    assert(Object.isFrozen(oneProp) === false);
    
    // ...假如删除了这个属性,则它会成为一个凝结对象.
    delete oneProp.p;
    assert(Object.isFrozen(oneProp) === true);
    
    // 一个不可扩大的对象,具有一个不可写但可设置的属性,则它照旧黑白凝结的.
    var nonWritable = { e: "plep" };
    Object.preventExtensions(nonWritable);
    Object.defineProperty(nonWritable, "e", { writable: false }); // 变得不可写
    assert(Object.isFrozen(nonWritable) === false);
    
    // 把这个属性改成不可设置,会让这个对象成为凝结对象.
    Object.defineProperty(nonWritable, "e", { configurable: false }); // 变得不可设置
    assert(Object.isFrozen(nonWritable) === true);
    
    // 一个不可扩大的对象,具有一个不可设置但可写的属性,则它照旧黑白凝结的.
    var nonConfigurable = { release: "the kraken!" };
    Object.preventExtensions(nonConfigurable);
    Object.defineProperty(nonConfigurable, "release", { configurable: false });
    assert(Object.isFrozen(nonConfigurable) === false);
    
    // 把这个属性改成不可写,会让这个对象成为凝结对象.
    Object.defineProperty(nonConfigurable, "release", { writable: false });
    assert(Object.isFrozen(nonConfigurable) === true);
    
    // 一个不可扩大的对象,值具有一个接见器属性,则它照旧黑白凝结的.
    var accessor = { get food() { return "yum"; } };
    Object.preventExtensions(accessor);
    assert(Object.isFrozen(accessor) === false);
    
    // ...但把这个属性改成不可设置,会让这个对象成为凝结对象.
    Object.defineProperty(accessor, "food", { configurable: false });
    assert(Object.isFrozen(accessor) === true);
    
    // 运用Object.freeze是凝结一个对象最轻易的要领.
    var frozen = { 1: 81 };
    assert(Object.isFrozen(frozen) === false);
    Object.freeze(frozen);
    assert(Object.isFrozen(frozen) === true);
    
    // 一个凝结对象也是一个密封对象.
    assert(Object.isSealed(frozen) === true);
    
    // 固然,更是一个不可扩大的对象.
    assert(Object.isExtensible(frozen) === false);        

Object.getPrototypeOf()

给定对象的原型。假如没有继续属性,则返回 null 。

    var obj = {};
    console.log(Object.getPrototypeOf(obj) === Object.prototype);        // true

    var fn = function () {};
    console.log(Object.getPrototypeOf(fn) === Function.prototype);        // true
    
    var arr = [];
    console.log(Object.getPrototypeOf(arr) === Array.prototype);        // true
    
    var q = {x:"x"};
    var p = Object.create(q);
    console.log(Object.getPrototypeOf(p) === q);                        // true
    
    // 假如参数不是援用范例,将抛出非常
    var num = 123;
    Object.getPrototypeOf(num);
    // "Uncaught TypeError: Object.getPrototypeOf called on non-object"

Object实例要领

Object.prototype.valueOf()

JavaScript 挪用 valueOf() 要领用来把对象转换成原始范例的值(数值、字符串和布尔值)。 你很少须要本身挪用此函数;当碰到一种须要转换成一个原始值状况时刻, JavaScript 会自动挪用此函数。

默许状况下, valueOf() 会被每一个对象Object继续。每一个内置对象都邑掩盖这个要领为了返回一个合理的值,假如对象没有原始值,valueOf() 就会返回对象本身。

你可以在本身的代码中运用 valueOf 要领用来把内置对象的值转换成原始值。 当你建立了自定义对象时,你可以掩盖 Object.prototype.valueOf() 并挪用来庖代 Object 要领。

JavaScript的很多内置对象都重写了该函数,以完成更适合本身的功用须要。因而,差别范例对象的valueOf()要领的返回值和返回值范例都可能差别。
《《JavaScript程序设计》—— 规范对象 Object》

    // Array:返回数组本身
    var arr = [1,2,3,"Array"];
    console.log(arr+" | "+(arr.valueOf() === arr));            //    "1,2,3,Array | true"    
    
    // String:返回当前字符串
    var str = "string";
    console.log(str.valueOf() === str);                        // true
    
    // Number:返回当前值
    var num = 123;
    console.log(num.valueOf() === num);                        // true
    
    // Boolean:返回当前布尔值
    var boo = true;                                            // 布尔值
    console.log(boo.valueOf() === boo);                        // true
    // 这里是布尔对象
    var boo2 = new Boolean(false);                            // 布尔对象
    console.log(boo2.valueOf());                            // false
    console.log(typeof boo2.valueOf());                        // boolean
    // 注重:这里对布尔对象操纵,返回的是原值的boolean范例,而不在是援用范例
    
    // Date:从1970年1月1日到如今的毫秒数
    var date = new Date();
    console.log(date.valueOf());                            // "1497789410938"
    
    // function: 返回当前函数
    var fn = function () {console.log("fn")};
    (fn.valueOf())();                                        // fn
    
    // Object: 返回对象本身
    var obj = {x:"obj.a"};
    console.log(obj.valueOf() === obj);                        // true                            

固然也可以掩盖要领:

    var obj = {a:1};
    obj.valueOf = function () {return this.a}
    
    console.log(obj+1);            // 2
    // 这里隐式挪用了valueOf要领

Object.prototype.toString()

每一个对象都有一个 toString() 要领,当对象被示意为文本值时或许当以希冀字符串的体式格局援用对象时,该要领被自动挪用。默许状况下,toString() 要领被每一个继续自Object的对象继续。假如此要领在自定义对象中未被掩盖,toString() 返回 “[object type]”,个中type是对象范例。

    // toString返回对象的字符串情势,默许状况下返回范例字符串
    var o1 = new Object();
    var o2 = {a:1};
    console.log(o1.toString());
    console.log(o2.toString());
    // "[object Object]"
    
    // 固然可以自定义它
    var obj = {};
    obj.toString = function () {return 1}
    console.log(2+obj);                    // 3

关于toString()更细致的可以看这里:

阮一峰 toString()的运用:推断数据范例

Object.prototype.toLocaleString()

Object’s toLocaleString 返回挪用 toString() 要领的结果。

    var num = 123;
    console.log(num.toString() === num.toLocaleString());            // true
    
    var obj = {};
    console.log(obj.toString() === obj.toLocaleString());            // true

Object.prototype.hasOwnProperty()

一切继续了 Object 的对象都邑继续到 hasOwnProperty 要领。这个要领可以用来检测一个对象是不是含有特定的本身属性;和 in 运算符差别,该要领会疏忽掉那些从原型链上继续到的属性。

    // 推断属性书否存在
    var obj = {x:"obj.x"};        
    console.log(obj.hasOwnProperty("x"));            // true                
    delete obj.x;
    console.log(obj.hasOwnProperty("x"));            // false                
    
    // 推断本身属性照样继续属性
    var p = {z:10};
    var o = Object.create(p);
    o.a = 20;        
    console.log(o.hasOwnProperty("a")+" | "+o.hasOwnProperty("z"));                
    // true | false
    
    console.log(o.hasOwnProperty("toString"));            // false
    console.log(o.hasOwnProperty("hasOwnProperty"));    // false
    
    // 遍历一个对象的本身属性
    var o1 = {z:"o1.z"};
    var o2 = Object.create(o1);
    o2.x = "o2.x";
    o2.y = "o2.y";
    
    for (var i in o2) {
        if (o2.hasOwnProperty(i)) {
            console.log("本身属性:"+i+" | "+"value:"+(o2[i]));
        } else {
            console.log(i+"不是本身属性")
        }
    }
    // "本身属性:x | value:o2.x"
    // "本身属性:y | value:o2.y"
    // "z不是本身属性"

hasOwnProperty也可以重写,所以须要注重这一点:

    var foo = {
        hasOwnProperty: function() {
            return false;
        },
        bar: 'Here be dragons'
    };
    
    foo.hasOwnProperty('bar'); // 一直返回 false
    
    // 假如忧郁这类状况,可以直接运用原型链上真正的 hasOwnProperty 要领
    ({}).hasOwnProperty.call(foo, 'bar'); // true
    
    // 也可以运用 Object 原型上的 hasOwnProperty 属性
    Object.prototype.hasOwnProperty.call(foo, 'bar'); // true
    

Object.prototype.isPrototypeOf()

isPrototypeOf 要领许可你搜检一个对象是不是存在于另一个对象的原型链上。

      function fn1() {
        this.a = "a";
    }
    function fn2() {
        this.b = "b";
    }
    
    fn2.prototype = new fn1();
    
    function fn3() {
        this.c = "c";
    }
    
    fn3.prototype = new fn2();
    
    function fn4() {
        this.d = "d";
    }
    
    fn4.prototype = new fn3();
    
    var test = new fn4();

    console.log(
        test.hasOwnProperty("a")+ " | "+test.hasOwnProperty("b")+" | "+test.hasOwnProperty("c")+" | "+test.hasOwnProperty("d")
    )
    // "false | false | false | true"

Object.prototype.propertyIsEnumerable()

每一个对象都有 propertyIsEnumerable 要领。该要领可以推断出指定对象里的属性是不是可罗列,也就是说该属性是不是可以经由过程 for…in 轮回等遍历到,不过有些属性虽然可以经由过程 for…in 轮回遍历到,但由于它们不是本身属性,而是从原型链上继续的属性,所以该要领也会返回false。假如对象没有指定的属性,该要领返回 false。

MDN:Object.prototype.propertyIsEnumerable()

    原文作者:Queen
    原文地址: https://segmentfault.com/a/1190000009819416
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞