对象 讲解之 扩展

以下内容是引用或者借鉴别人的,自己只是做个笔记,方便学习。理解错误的地方,欢迎评论。如有侵权,私聊我删除,未经允许,不准作为商业用途

静态方法

  • create() 创建一个对象
// 第一个参数是新创建对象的原型对象
let obj = { a: 123 ,f: function(){}};
console.log(Object.create(obj))
image.png
// 第二个参数是新创建对象的属性
let obj = { a: 123 ,f: function(){}};
console.log(Object.create(obj,{b: {value: 456}}))
image.png
  • defineProperty()在一个对象上定义一个新属性或者修改一个对象的现有属性,并返回此对象
const object1 = {a: 123 };
Object.defineProperty(object1, 'property1', {
  value: 42,
  writable: false,
  enumerable: true,
  configurable: true
});
object1.property1 = 77;// throws an error in strict mode
console.log(object1.property1); // 42

let bValue = 0;
Object.defineProperty(object1, 'property2', {
  get() { return bValue; },
  set(newValue) { bValue = newValue; },
  enumerable: true,
  configurable: true
});
  • defineProperties()在一个对象上定义新的属性或修改现有属性,并返回该对象。
let object1 = { a: 123 };
Object.defineProperties(object1, {
  property1: {
    value: 42,
    writable: false,
    enumerable: true,
    configurable: true
  },
  property2: {
    value: "hello",
    writable: true,
    enumerable: true,
    configurable: true
  }
});
image.png
  • preventExtensions()让一个对象变的不可扩展,也就是永远不能再添加新的属性,可以修改已有属性。
const obj = {
  prop: 42
};
Object.preventExtensions(obj);
obj.prop = 33;    // 33
obj.prop2 = 33;// Cannot add property prop2, object is not extensible
  • isExtensible() 判断一个对象是否是可扩展的
const obj = {
  prop: 42
};
Object.preventExtensions(obj);
Object.isExtensible(obj); //false

// 是不可扩展
Object.isExtensible(obj)// false

// 是非密封
Object.isSealed(obj)//false

// 是非冻结
Object.isFrozen (obj); //false
  • seal()封闭一个对象,指不能添加新的属性,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性,但可能可以修改已有属性的值的对象。
var o2 = {b: 1}
o2.d = 2    //添加成功
var obj2 = Object.seal(o2);
obj2 === o2         //true  方法返回原对象,栈指针指向同一块内存
o2.b = 111       //修改b属性值成功
o2.f = 222       //Cannot add property f, object is not extensible
delete o2.b      //Cannot delete property 'b' of #
 
 
  • isSealed() 判断一个对象是否被密封
var o2 = {b: 1}
Object.seal(o2);

// 密封对象是不可扩展
Object.isExtensible(o2)// false

// 密封对象是密封
Object.isSealed(o2)//true

// 密封对象是非冻结
Object.isFrozen (o2); //false
// 一个不可扩展的对象,其所有键拥有不可配置但可写的属性,将会成为密封对象
//对应的键不可配置,则这个属性会成密封
var o2 = {b: 1}
Object.preventExtensions(o2);
Object.defineProperty(o2, "b", { configurable: false });
Object.isSealed(o2)//true
Object.isSealed(o2.b)//true
  • freeze() 冻结一个对象,将不可进行一切操作
const obj = {
  prop: 42
};
Object.freeze(obj);
obj.prop = 33;// Throws an error in strict mode
console.log(obj.prop);// expected output: 42
  • isFrozen() 判断一个对象是否已经被冻结
const obj = {
  prop: 42
};
Object.freeze(obj);

// 冻结对象是不可扩展
Object.isExtensible(obj)// false

// 冻结对象是密封
Object.isSealed(obj)//true

// 冻结对象是冻结
Object.isFrozen (obj); //true
// 一个不可扩展的对象,其所有键拥有不可配置且不可写的属性,将会成为冻结对象
//对应的键不可写,则这个属性会成冻结
var o2 = {b: 1}
Object.preventExtensions(o2);
Object.defineProperty(o2, "b", { configurable: false });
Object.defineProperty(o2, "b", { writable: false});
Object.isFrozen(o2)//true
Object.isFrozen(o2.b)//true
  • getOwnPropertyDescriptor() 返回指定对象一个自身属性(非继承属性)的描述对象
let obj = { foo: 123 };
console.log(obj)
console.log(Object.getOwnPropertyDescriptor(obj, 'foo'))
//  {
//    value: 123,
//    writable: true,
//    enumerable: true,
//    configurable: true
//  }
image.png
let obj2 = Object.create({},{foo:{value:456,enumerable:false}})
console.log(obj2)
console.log(Object.getOwnPropertyDescriptor(obj2, 'foo'))
//  {
//    value: 456,
//    writable: false,
//    enumerable: false,
//    configurable: false
//  }

image.png

小知识:描述对象的enumerable属性,称为“可枚举性”,如果为false,属性将会显示浅红色,某些操作(for...inObject.keys()Object.values()Object.entries()JSON.stringify()Object.assign()等)会忽略当前属性,直接跳过,所有Class 的原型的方法都是不可枚举的

let obj2 = Object.create({},{foo:{value:456,enumerable:false}})
Object.keys(obj2) //[]
  • getOwnPropertyDescriptors()返回指定对象所有自身属性(非继承属性)的描述对象
const obj = {
  foo: 123,
  get bar() { return 'abc' }
};
Object.getOwnPropertyDescriptors(obj)
// { 
//   foo:
//    { value: 123,
//      writable: true,
//      enumerable: true,
//      configurable: true },
//   bar:
//    { get: [Function: get bar],
//      set: undefined,
//      enumerable: true,
//      configurable: true }
// }
  • getOwnPropertyNames()返回一个由指定对象的所有自身属性的属性名(不包括Symbol值作为名称的属性)组成的数组
var arr = ["a", "b", "c"];
Object.getOwnPropertyNames(arr); // ["0", "1", "2", "length"]

// 类数组对象
var obj = { 0: "a", 1: "b", 2: "c"};
Object.getOwnPropertyNames(obj); // ["0", "1", "2"]

//不可枚举属性可以被找到,Symbol值不可以被找到
let obj2 = Object.create({},{foo:{value:456,enumerable:false}})
obj2[Symbol("a")] = 123;
Object.getOwnPropertyDescriptor(obj2, 'foo')
Object.getOwnPropertyNames(obj2) //['foo']
  • getOwnPropertySymbols() 返回一个给定对象自身的所有 Symbol 属性的数组
var obj = {
  a: 'a',
  [Symbol("a")]: 123,
  [Symbol("b")]: 456,
};
var objectSymbols = Object.getOwnPropertySymbols(obj);
Object.getOwnPropertySymbols(obj)// [Symbol(a), Symbol(b)]

<<============以下是新方法==========>>

  • is()用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。二者区别:一是+0不等于-0,二是NaN等于自身
Object.is('foo', 'foo')  // true
Object.is({}, {})  // false

+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
  • assign()用于对象的合并,将源对象的所有可枚举属性,复制到目标对象,实行的是浅拷贝
const target = { a: 1, b: 1 };
const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

// undefined,null跳过
const obj = {a: 1};
Object.assign(obj) === obj // true
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true

// 浅拷贝
const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
obj2.a.b // 2

//同名属性的替换
const target = { a: { b: 'c', d: 'e' } }
const source = { a: { b: 'hello' } }
Object.assign(target, source)
// { a: { b: 'hello' } }

// 数组
Object.assign([],[1,3],[2])  // [2, 3]
  • setPrototypeOf()用来设置一个对象的原型对象,返回参数对象本身
// 实现方法
function setPrototypeOf(obj, proto) {
  obj.__proto__ = proto;
  return obj;
}
let proto = {};
let obj = { x: 10 };
Object.setPrototypeOf(obj, proto);
proto.y = 20;
proto.z = 40;
console.log(obj)

Object.setPrototypeOf({}, null);//{}
Object.setPrototypeOf(undefined, {})// TypeError: Object.setPrototypeOf called on null or undefined
Object.setPrototypeOf(null, {})// TypeError: Object.setPrototypeOf called on null or undefined
image.png
  • getPrototypeOf()用于读取一个对象的原型对象
function Rectangle() {}
const rec = new Rectangle();
Object.getPrototypeOf(rec) === Rectangle.prototype// true
Object.setPrototypeOf(rec, Object.prototype);
Object.getPrototypeOf(rec) === Rectangle.prototype// false

Object.getPrototypeOf(1) === Number.prototype // true
Object.getPrototypeOf('foo') === String.prototype // true
Object.getPrototypeOf(true) === Boolean.prototype // true
Object.getPrototypeOf(null)// TypeError: Cannot convert undefined or null to object
Object.getPrototypeOf(undefined)// TypeError: Cannot convert undefined or null to object
  • keys()返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键名
var obj = { foo: 'bar', baz: 42 };
Object.keys(obj)
// ["foo", "baz"]
  • values()返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键值
const obj = { foo: 'bar', baz: 42 };
Object.values(obj)  // ["bar", 42]

//enumerable默认是false
const obj = Object.create({}, {p: {value: 42}});
Object.values(obj) // []

// 可遍历
const obj = Object.create({}, {p:{ value: 42,enumerable: true}});
Object.values(obj) // [42]

//过滤属性名为 Symbol 值的属性
Object.values({ [Symbol()]: 123, foo: 'abc' });  // ['abc']

//字符串,会返回各个字符组成的一个数组
Object.values('foo')  // ['f', 'o', 'o']

// 属性名为数值的属性,是按照数值大小,从小到大遍历的
const obj = { 100: 'a', 2: 'b', 7: 'c' };
Object.values(obj)  // ["b", "c", "a"]
  • entries()返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键值对数组
const obj = { foo: 'bar', baz: 42 };
Object.entries(obj)
// [ ["foo", "bar"], ["baz", 42] ]

小结keys(), values(),entries()方法行为一样,只是返回值不一样

let {keys, values, entries} = Object;
let obj = { a: 1, b: 2, c: 3 };

for (let key of keys(obj)) {
  console.log(key); // 'a', 'b', 'c'
}

for (let value of values(obj)) {
  console.log(value); // 1, 2, 3
}

for (let [key, value] of entries(obj)) {
  console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]
}
  • fromEntrie()entries()的逆操作,用于将一个键值对数组转为对象
Object.fromEntries([
  ['foo', 'bar'],
  ['baz', 42]
])
// { foo: "bar", baz: 42 }

// Map=>Object
const entries = new Map([
  ['foo', 'bar'],
  ['baz', 42]
]);
Object.fromEntries(entries)  // { foo: "bar", baz: 42 }

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

静态方法图解

image.png

实例方法

  • toString() 返回 "[object type]",其中 type 是对象的类型
var o = new Object();
o.toString(); // [object Object]
var toString = Object.prototype.toString;

toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]

//Since JavaScript 1.8.5
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]

实例方法图解

image.png

你可能感兴趣的:(对象 讲解之 扩展)