Object 构造函数的方法

Posted ikoala-zsd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Object 构造函数的方法相关的知识,希望对你有一定的参考价值。

Object.assign() (es6)

用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

Object.assign(target, ...sources) // target 目标对象。 sources 源对象。

    ‘use strict‘;

    let obj1 = { a: 0 , b: { c: 0}};
    let obj2 = Object.assign({}, obj1);
    console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
  
    obj1.a = 1;
    console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
    console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
  
    obj2.a = 2;
    console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
    console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}}
  
    obj2.b.c = 3;
    console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
    console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}}
  
    // Deep Clone
    obj1 = { a: 0 , b: { c: 0}};
    let obj3 = JSON.parse(JSON.stringify(obj1));
    obj1.a = 4;
    obj1.b.c = 4;
    console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}
    
    
    //合并对象
    
    var o1 = { a: 1 };
    var o2 = { b: 2 };
    var o3 = { c: 3 };

    var obj = Object.assign(o1, o2, o3);
    console.log(obj); // { a: 1, b: 2, c: 3 }
    console.log(o1);  // { a: 1, b: 2, c: 3 },     注意目标对象自身也会改变。
    
    //合并具有相同属性的对象
    var o1 = { a: 1, b: 1, c: 1 };
    var o2 = { b: 2, c: 2 };
    var o3 = { c: 3 };

    var obj = Object.assign({}, o1, o2, o3);
    console.log(obj); // { a: 1, b: 2, c: 3 }
    
    //拷贝 symbol 类型的属性
    var o1 = { a: 1 };
    var o2 = { [Symbol(‘foo‘)]: 2 };

    var obj = Object.assign({}, o1, o2);
    console.log(obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox)
    Object.getOwnPropertySymbols(obj); // [Symbol(foo)]
    
    //继承属性和不可枚举属性是不能拷贝的
    var obj = Object.create({foo: 1}, { // foo 是个继承属性。
        bar: {
            value: 2  // bar 是个不可枚举属性。
        },
        baz: {
            value: 3,
            enumerable: true  // baz 是个自身可枚举属性。
        }
    });
    
    var copy = Object.assign({}, obj);
    console.log(copy); // { baz: 3 }
    
    // 原始类型会被包装为对象
    var v1 = "abc";
    var v2 = true;
    var v3 = 10;
    var v4 = Symbol("foo")
    
    var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); 
    // 原始类型会被包装,null 和 undefined 会被忽略。
    // 注意,只有字符串的包装对象才可能有自身可枚举属性。
    console.log(obj); // { "0": "a", "1": "b", "2": "c" }
    

Object.create()

创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。

Object.create(proto, [propertiesObject])

proto

新创建对象的原型对象。

propertiesObject

可选。如果没有指定为 undefined,则是要添加到新创建对象的可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()的第二个参数。

    //用 Object.create实现类式继承
    // Shape - 父类(superclass)
    function Shape() {
      this.x = 0;
      this.y = 0;
    }
    
    // 父类的方法
    Shape.prototype.move = function(x, y) {
      this.x += x;
      this.y += y;
      console.info(‘Shape moved.‘);
    };
    
    // Rectangle - 子类(subclass)
    function Rectangle() {
      Shape.call(this); // call super constructor.
    }
    
    // 子类续承父类
    Rectangle.prototype = Object.create(Shape.prototype);
    Rectangle.prototype.constructor = Rectangle;
    
    var rect = new Rectangle();
    
    console.log(‘Is rect an instance of Rectangle?‘,
      rect instanceof Rectangle); // true
    console.log(‘Is rect an instance of Shape?‘,
      rect instanceof Shape); // true
    rect.move(1, 1); // Outputs, ‘Shape moved.‘
    
    //使用 Object.create 的 propertyObject参数
    
    var o;

    // 创建一个原型为null的空对象
    o = Object.create(null);
    
    
    o = {};
    // 以字面量方式创建的空对象就相当于:
    o = Object.create(Object.prototype);
    
    
    o = Object.create(Object.prototype, {
      // foo会成为所创建对象的数据属性
      foo: { 
        writable:true,
        configurable:true,
        value: "hello" 
      },
      // bar会成为所创建对象的访问器属性
      bar: {
        configurable: false,
        get: function() { return 10 },
        set: function(value) {
          console.log("Setting `o.bar` to", value);
        }
      }
    });
    
    
    function Constructor(){}
    o = new Constructor();
    // 上面的一句就相当于:
    o = Object.create(Constructor.prototype);
    // 当然,如果在Constructor函数中有一些初始化代码,Object.create不能执行那些代码
    
    
    // 创建一个以另一个空对象为原型,且拥有一个属性p的对象
    o = Object.create({}, { p: { value: 42 } })
    
    // 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的:
    o.p = 24
    o.p
    //42
    
    o.q = 12
    for (var prop in o) {
       console.log(prop)
    }
    //"q"
    
    delete o.p
    //false
    
    //创建一个可写的,可枚举的,可配置的属性p
    o2 = Object.create({}, {
      p: {
        value: 42, 
        writable: true,
        enumerable: true,
        configurable: true 
      } 
    });

Object.defineProperty() 和 Object.defineProperties()

直接在一个对象上定义新的属性或修改现有属性,并返回该对象。

           configurable enumerable  value   writable    get     set
数据描述符   Yes         Yes         Yes     Yes          No     No
存取描述符   Yes         Yes         No      No           Yes    Yes
如果一个描述符不具有value,writable,get 和 set 任意一个关键字,那么它将被认为是一个数据描述符。如果一个描述符同时有(value或writable)和(get或set)关键字,将会产生一个异常。
// 显式
Object.defineProperty(obj, "key", {
  enumerable: false,
  configurable: false,
  writable: false,
  value: "static"
});


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

Object.entries()

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

Object.entries(obj)
const obj = { foo: ‘bar‘, baz: 42 };
console.log(Object.entries(obj)); // [ [‘foo‘, ‘bar‘], [‘baz‘, 42] ]

// array like object
const obj = { 0: ‘a‘, 1: ‘b‘, 2: ‘c‘ };
console.log(Object.entries(obj)); // [ [‘0‘, ‘a‘], [‘1‘, ‘b‘], [‘2‘, ‘c‘] ]

// array like object with random key ordering
const anObj = { 100: ‘a‘, 2: ‘b‘, 7: ‘c‘ };
console.log(Object.entries(anObj)); // [ [‘2‘, ‘b‘], [‘7‘, ‘c‘], [‘100‘, ‘a‘] ]

// getFoo is property which isn‘t enumerable
const myObj = Object.create({}, { getFoo: { value() { return this.foo; } } });
myObj.foo = ‘bar‘;
console.log(Object.entries(myObj)); // [ [‘foo‘, ‘bar‘] ]

// non-object argument will be coerced to an object
console.log(Object.entries(‘foo‘)); // [ [‘0‘, ‘f‘], [‘1‘, ‘o‘], [‘2‘, ‘o‘] ]

// iterate through key-value gracefully
const obj = { a: 5, b: 7, c: 9 };
for (const [key, value] of Object.entries(obj)) {
  console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
}
// Or, using array extras
Object.entries(obj).forEach(([key, value]) => {
console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});


// 将Object转换为Map

var obj = { foo: "bar", baz: 42 }; 
var map = new Map(Object.entries(obj));
console.log(map); // Map { foo: "bar", baz: 42 }

Object.freeze()

可以冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。也就是说,这个对象永远是不可变的。该方法返回被冻结的对象。

const object1 = {
  property1: 42
};

const object2 = Object.freeze(object1);

object2.property1 = 33;
// Throws an error in strict mode

console.log(object2.property1);
// expected output: 42


// 冻结数组
let a = [0];
Object.freeze(a); // The array cannot be modified now.

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

Object.getOwnPropertyDescriptor()

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

Object.getOwnPropertyDescriptor(obj, prop) //obj 需要查找的目标对象 prop 目标对象内属性名称(String类型)
var o, d;

o = { get foo() { return 17; } };
d = Object.getOwnPropertyDescriptor(o, "foo");
// d {
//   configurable: true,
//   enumerable: true,
//   get: /*the getter function*/,
//   set: undefined
// }

o = { bar: 42 };
d = Object.getOwnPropertyDescriptor(o, "bar");
// d {
//   configurable: true,
//   enumerable: true,
//   value: 42,
//   writable: true
// }

o = {};
Object.defineProperty(o, "baz", {
  value: 8675309,
  writable: false,
  enumerable: false
});
d = Object.getOwnPropertyDescriptor(o, "baz");
// d {
//   value: 8675309,
//   writable: false,
//   enumerable: false,
//   configurable: false
// }

Object.getOwnPropertyNames(obj)

返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。

// 使用Array.forEach输出属性名和属性值
Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) {
  console.log(val + " -> " + obj[val]);
});
//不可枚举属性
var my_obj = Object.create({}, {
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false
  }
});
my_obj.foo = 1;

console.log(Object.getOwnPropertyNames(my_obj).sort()); // ["foo", "getFoo"]

//该方法不会获取到原型链上的属性
function ParentClass() {}
ParentClass.prototype.inheritedMethod = function() {};

function ChildClass() {
  this.prop = 5;
  this.method = function() {};
}

ChildClass.prototype = new ParentClass;
ChildClass.prototype.prototypeMethod = function() {};

console.log(
  Object.getOwnPropertyNames(
    new ChildClass()  // ["prop", "method"]
  )
);

Object.getPrototypeOf(obj)

返回指定对象的原型(内部[[Prototype]]属的值)

var proto = {};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true

var reg = /a/;
Object.getPrototypeOf(reg) === RegExp.prototype; // true

Object.is(value1, value2);

判断两个值是否是相同的值。

Object.is(‘foo‘, ‘foo‘);     // true
Object.is(window, window);   // true

Object.is(‘foo‘, ‘bar‘);     // false
Object.is([], []);           // false

var test = { a: 1 };
Object.is(test, test);       // true

Object.is(null, null);       // true

// 特例
Object.is(0, -0);            // false
Object.is(-0, -0);           // true
Object.is(NaN, 0/0);         // true

Object.preventExtensions(obj)

让一个对象变的不可扩展,也就是永远不能再添加新的属性。

// Object.preventExtensions将原对象变的不可扩展,并且返回原对象.
var obj = {};
var obj2 = Object.preventExtensions(obj);
obj === obj2;  // true
 
// 字面量方式定义的对象默认是可扩展的.
var empty = {};
Object.isExtensible(empty) //=== true
 
// ...但可以改变.
Object.preventExtensions(empty);
Object.isExtensible(empty) //=== false
 
// 使用Object.defineProperty方法为一个不可扩展的对象添加新属性会抛出异常.
var nonExtensible = { removable: true };
Object.preventExtensions(nonExtensible);
Object.defineProperty(nonExtensible, "new", { value: 8675309 }); // 抛出TypeError异常
 
// 在严格模式中,为一个不可扩展对象的新属性赋值会抛出TypeError异常.
function fail()
{
  "use strict";
  nonExtensible.newProperty = "FAIL"; // throws a TypeError
}
fail();
 
// 一个不可扩展对象的原型是不可更改的,__proto__是个非标准魔法属性,可以更改一个对象的原型.
var fixed = Object.preventExtensions({});
fixed.__proto__ = { oh: "hai" }; // 抛出TypeError异常

Object.isExtensible(obj)

判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。

默认情况下,对象是可扩展的:即可以为他们添加新的属性。以及它们的 proto 属性可以被更改。Object.preventExtensions,Object.seal 或 Object.freeze 方法都可以标记一个对象为不可扩展(non-extensible)。

// 新对象默认是可扩展的.
var empty = {};
Object.isExtensible(empty); // === true

// ...可以变的不可扩展.
Object.preventExtensions(empty);
Object.isExtensible(empty); // === false

// 密封对象是不可扩展的.
var sealed = Object.seal({});
Object.isExtensible(sealed); // === false

// 冻结对象也是不可扩展.
var frozen = Object.freeze({});
Object.isExtensible(frozen); // === false

Object.seal()

封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要可写就可以改变。

var obj = {
  prop: function() {},
  foo: ‘bar‘
};

// New properties may be added, existing properties
// may be changed or removed.
obj.foo = ‘baz‘;
obj.lumpy = ‘woof‘;
delete obj.prop;

var o = Object.seal(obj);

o === obj; // true
Object.isSealed(obj); // === true

// Changing property values on a sealed object
// still works.
obj.foo = ‘quux‘;

// But you can‘t convert data properties to accessors,
// or vice versa.
Object.defineProperty(obj, ‘foo‘, {
  get: function() { return ‘g‘; }
}); // throws a TypeError

// Now any changes, other than to property values,
// will fail.
obj.quaxxor = ‘the friendly duck‘;
// silently doesn‘t add the property
delete obj.foo;
// silently doesn‘t delete the property

// ...and in strict mode such attempts
// will throw TypeErrors.
function fail() {
  ‘use strict‘;
  delete obj.foo; // throws a TypeError
  obj.sparky = ‘arf‘; // throws a TypeError
}
fail();

// Attempted additions through
// Object.defineProperty will also throw.
Object.defineProperty(obj, ‘ohai‘, {
  value: 17
}); // throws a TypeError
Object.defineProperty(obj, ‘foo‘, {
  value: ‘eit‘
}); // changes existing property value

Object.isSealed()

判断一个对象是否被密封。

// 新建的对象默认不是密封的.
var empty = {};
Object.isSealed(empty); // === false

// 如果你把一个空对象变的不可扩展,则它同时也会变成个密封对象.
Object.preventExtensions(empty);
Object.isSealed(empty); // === true

// 但如果这个对象不是空对象,则它不会变成密封对象,因为密封对象的所有自身属性必须是不可配置的.
var hasProp = { fee: "fie foe fum" };
Object.preventExtensions(hasProp);
Object.isSealed(hasProp); // === false

// 如果把这个属性变的不可配置,则这个对象也就成了密封对象.
Object.defineProperty(hasProp, "fee", { configurable: false });
Object.isSealed(hasProp); // === true

// 最简单的方法来生成一个密封对象,当然是使用Object.seal.
var sealed = {};
Object.seal(sealed);
Object.isSealed(sealed); // === true

// 一个密封对象同时也是不可扩展的.
Object.isExtensible(sealed); // === false

// 一个密封对象也可以是一个冻结对象,但不是必须的.
Object.isFrozen(sealed); // === true ,所有的属性都是不可写的
var s2 = Object.seal({ p: 3 });
Object.isFrozen(s2); // === false, 属性"p"可写

var s3 = Object.seal({ get p() { return 0; } });
Object.isFrozen(s3); // === true ,访问器属性不考虑可写不可写,只考虑是否可配置

Object.keys(obj)

返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。

// simple array
var arr = [‘a‘, ‘b‘, ‘c‘];
console.log(Object.keys(arr)); // console: [‘0‘, ‘1‘, ‘2‘]

// array like object
var obj = { 0: ‘a‘, 1: ‘b‘, 2: ‘c‘ };
console.log(Object.keys(obj)); // console: [‘0‘, ‘1‘, ‘2‘]

// array like object with random key ordering
var anObj = { 100: ‘a‘, 2: ‘b‘, 7: ‘c‘ };
console.log(Object.keys(anObj)); // console: [‘2‘, ‘7‘, ‘100‘]

// getFoo is a property which isn‘t enumerable
var myObj = Object.create({}, {
  getFoo: {
    value: function () { return this.foo; }
  } 
});
myObj.foo = 1;
console.log(Object.keys(myObj)); // console: [‘foo‘]

Object.values(obj)

返回一个给定对象自己的所有可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。

var obj = { foo: ‘bar‘, baz: 42 };
console.log(Object.values(obj)); // [‘bar‘, 42]

// array like object
var obj = { 0: ‘a‘, 1: ‘b‘, 2: ‘c‘ };
console.log(Object.values(obj)); // [‘a‘, ‘b‘, ‘c‘]

// array like object with random key ordering
// when we use numeric keys, the value returned in a numerical order according to the keys
var an_obj = { 100: ‘a‘, 2: ‘b‘, 7: ‘c‘ };
console.log(Object.values(an_obj)); // [‘b‘, ‘c‘, ‘a‘]

// getFoo is property which isn‘t enumerable
var my_obj = Object.create({}, { getFoo: { value: function() { return this.foo; } } });
my_obj.foo = ‘bar‘;
console.log(Object.values(my_obj)); // [‘bar‘]

// non-object argument will be coerced to an object
console.log(Object.values(‘foo‘)); // [‘f‘, ‘o‘, ‘o‘]

Object.setPrototypeOf(obj, prototype)

设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或 null

var dict = Object.setPrototypeOf({}, null);

以上是关于Object 构造函数的方法的主要内容,如果未能解决你的问题,请参考以下文章

在 Visual Studio 中创建构造函数的代码片段或快捷方式

Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | DexClassLoader 构造函数 | 参考 Dalvik 的 DexClassLoader 类加载流程 )(代码片段

Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | DexClassLoader 构造函数 | 参考 Dalvik 的 DexClassLoader 类加载流程 )(代码片段

Object构造函数的方法 之Object.entries()

Javascript-基础-Object创建对象

Object 构造函数的方法