欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

object

程序员文章站 2022-05-16 14:21:57
...

1.创建对象的几种方法

(1) let obj = {name: 'john'}
    let obj1 = new Object({name: 'john'})
(2) let obj2 = Object.create(obj)
(3) let A = function () {
      this.name = 'john'
    }
    let obj3 = new A()
复制代码

2.object的常用操作

(1)获取object的key值

const a = {
    name: 'john',
    age: 16
}
for (let key in a) {
    console.log(key) // name age
}
复制代码

(2) Object.keys()

方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。(区别: for-in 循环还会枚举其原型链上的属性)

const a = {
    name: 'john',
    age: 16
}
console.log(Object.keys(a)) // ["name", "age"]
复制代码

(3) Object.assign()

1.复制对象
const copy = Object.assign({age: 18}, a)
console.log(copy); // { name: 'john', age: 16 }
复制代码

注:如果目标对象中的属性具有相同的键,后来属性将覆盖之前的属性。该方法使用源对象的[[Get]]和目标对象的[[Set]],所以它会调用相关 getter 和 setter。 此方法拷贝的是属性值,假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。

比如:
a.language = {CH: true}
const a1 = Object.assign({},a)
操作
a.language.CH = false
console.log(a1) // { name: 'john', age: 16 ,language: {CH: false}}
复制代码

我们发现a1值拷贝了a的引用,在修改a的CH的值时,a1的值也随之改变。

浅拷贝只解决了第一层的问题,如果接下去的值中还有对象的话,两者就享有了相同的引用。要解决这个问题,我们需要引入深拷贝

因此我们常用如下方法进行深拷贝
a = {
    name: 'john',
    age: 16,
    language: {CH: true}
}
let obj3 = JSON.parse(JSON.stringify(a))
a.language.CH = false
console.log(a.language) // {CH: false}
console.log(obj3.language) // {CH: true}
复制代码

但该方法也是有局限性的:

  • 会忽略 undefined
  • 会忽略 symbol
  • 不能序列化函数
  • 不能解决循环引用的对象

这个函数可以解决大部分的问题,并且该函数是处理深拷贝性能最快的。如果你的数据中含有 【函数、undefined、symbol】这三种情况,可以使用 lodash 的深拷贝函数

(2) 合并对象

const obj1 = {a: 1}
const obj2 = {b: 2}
const obj3 = {c: 3}
let obj = Object.assign(obj1, obj2, obj3)
将obj2、obj3合并到了目标对象obj1,因此obj1也发生了改变
console.log(obj) // {a: 1, b: 2, c: 3}
console.log(obj1) // {a: 1, b: 2, c: 3}
复制代码

拷贝或合并失败的情况

(1)继承属性和不可枚举属性是不能拷贝的
let obj = Object.create({foo: 1}, {
    bar: {
        value: 2  // bar 是个不可枚举属性。
    },
    baz: {
        value: 3,
        enumerable: true  // baz 是个自身可枚举属性。
    }
})
let copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }

(2)原始类型会被包装为object
let v1 = 'abc'
let v2 = true
let v3 = 10
let v4 = Symbol('foo')

let obj = Object.assign({},v1, null, v2, undefined, v3, v4)
// 原始类型会被包装,null 和 undefined 会被忽略。
// 注意,只有字符串的包装对象才可能有自身可枚举属性。
console.log(obj); // { "0": "a", "1": "b", "2": "c" }

(3)异常会打断后续拷贝任务
let target = Object.defineProperty({}, "foo", {
    value: 1,
    writable: false
}); // target 的 foo 属性是个只读属性。
Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4});
// TypeError: "foo" is read-only
// 注意这个异常是在拷贝第二个源对象的第二个属性时发生的。

console.log(target.bar);  // 2,说明第一个源对象拷贝成功了。
console.log(target.foo2); // 3,说明第二个源对象的第一个属性也拷贝成功了。
console.log(target.foo);  // 1,只读属性不能被覆盖,所以第二个源对象的第二个属性拷贝失败了。
console.log(target.foo3); // undefined,异常之后 assign 方法就退出了,第三个属性是不会被拷贝到的。
console.log(target.baz);  // undefined,第三个源对象更是不会被拷贝到的。
复制代码

参考:Object.assign()

(4) Object.is()

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

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
复制代码

(5) Object.create()

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

const person = {
  isHuman: false,
  printIntroduction: function () {
    console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`)
  }
}

const me = Object.create(person)

me.name = "Matthew" // "name" is a property set on "me", but not on "person"
me.isHuman = true // inherited properties can be overwritten

me.printIntroduction()


复制代码

新对象 me 的__proto__ 即为原有对象 person,在 me 的原型链上

me.__proto__ === person // true
复制代码

第二个参数是可选的,主要用于指定我们创建的对象的一些属性。

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.create()实现类的继承

// 父类(superclass)
function Shape() {
    this.x = 0
    this.y = 0
}
// 父类的方法
Shape.prototype.move = function(x, y) {
    this.x += x
    this.y += y
    console.log('Shape moved.')
}
// 子类(subclass)
function Reactangle () {
   Shape.call(this) // call super constructor
}
// 子类继承父类
Rectangle.prototype = Object.create(Shape.prototype)
Rectangle.prototype.constructor = Rectangle
复制代码

(6) Object.freeze()

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

const object1 = {
  property1: 42
};

const object2 = Object.freeze(object1);

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

console.log(object2.property1); // 42
复制代码

(7) Object.defineProperty() 该方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。

let obj = {}
Object.defineProperty(obj, "key", {
    enumerable: true,
    configurable: true,
    writable: true,
    value: "static"
})
复制代码

简单实现双向数据绑定mvvm

<input id="input" />

const data = {}
const input = document.getElementById('input')
Object.defineProperty(data, 'text', {
    set(value) {
        input.value = value
        this.value = value
    }
})
input.onchange = function(e) {
    data.text = e.target.value
}
复制代码

(8) Object.isFrozen()

判断一个对象是否被冻结

Object.isFrozen({}) // false
复制代码

(9) Object.isExensible()

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

// 新对象默认是可扩展的
let empty = {}
Object.isExetnsible(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
复制代码

(10) Object.isSealed()

判断一个对象是否是密封的(sealed)。

(11) Object.seal()

可以让一个对象密封,并返回被密封后的对象。密封对象是指那些不能添加新的属性,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性,但可能可以修改已有属性的值的对象。

(12) Object.values()

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

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

let obj = {0: 'a',1: 'b',2: 'c'}
console.log(Object.value(obj)) // ['a', 'b', 'c']

let obj = {100: 'a', 2: 'b', 7: 'c'}
console.log(Object.values(obj)) // ['b', 'c', 'a']

let my_obj = Object.create({}, {getFoo: {value: function() {return this.foo}}})
my_obj.foo = 'bar'
console.log(Object.values(my_obj)) // ['bar']

console.log(Object.values('foo')) // ['f', 'o', 'o']
复制代码
  1. 生成动态的key值
const obj = {}
obj['a' + 'bc'] = 123
console.log(obj) // {abc: 123}
复制代码

4.修改一个对象的键名

let key = 'abc'
let obj = {key: 'value'}
obj[key] = obj['key']
// 删除原来的键
delete obj['key']
console.log(obj['abc'])
复制代码

5.其他

let a = {"":123, " ":1}
console.log(a[""]) // 123
console.log(a[" "]) // 1
复制代码

上一篇: 屏幕录制

下一篇: Object