JS非常用函数

2 阅读4分钟

一、Object.freeze():冻结对象,防止对象被修改

Object.freeze() 是JavaScript中的一个方法,用于冻结一个对象。被冻结的对象不能再被修改。

具体来说,它做了两件事情:

  • 防止添加新的属性:尝试添加新属性将失败,不会抛出错误,但新属性不会被添加到对象中。
  • 防止删除属性:尝试删除对象的任何属性都将失败,不会抛出错误。
  • 不能修改已有属性的值
  • 不能修改原型
  • 不能修改已有属性的可枚举性、可配置性、可写性

1、基本使用

var obj = {
    name: '张三',
    age: 18,
    address: '上海市'
}
obj.__proto__.habit = '运动'
 
// 冻结对象
Object.freeze(obj)
 
// 不能添加新属性
obj.sex = '男'
console.log(obj)    // {name: "张三", age: 18, address: "上海市"}
 
// 不能删除原有属性
delete obj.age
console.log(obj)    // {name: "张三", age: 18, address: "上海市"}
 
// 不能修改已有属性的值
obj.name = '李四'
console.log(obj)    // {name: "张三", age: 18, address: "上海市"}
 
// 不能修改原型
obj.__proto__ = '随便什么值'
console.log(obj.__proto__)  // {habit: "运动", constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, …}
 
// 不能修改已有属性的可枚举性、可配置性、可写性
Object.defineProperty(obj,'address',{ // TypeError: Cannot redefine property: address
    enumerable: false,// 表示是否可以枚举。直接在对象上定义的属性,基本默认true
    configurable: false,// 表示能否通过delete删除属性,能否修改属性的特性
    writable: true// 表示能否修改属性的值。直接在对象上定义的属性,基本默认true
})

Object.freeze()的返回值就是被冻结的对象,该对象完全等于传入的对象,所以我们一般不需要接收返回值。

2、冻结数组

数组本质也就是对象,只不过对象的key是下标,所以也可以冻结

var arr = [1,2,3,4,5]
Object.freeze(arr)
arr[0]='新值'
console.log(arr)    // [1, 2, 3, 4, 5]

2.1、浅冻结

var obj = {
    name: '张三',
    info: {
        a: 1,
        b: 2
    }
}
Object.freeze(obj)

obj.name = '李四'
console.log(obj)    // {info: {a: 1, b: 2},name: "张三"}

obj.info.a = 66
console.log(obj.info)   // {a: 66, b: 2}

可以看到对象中如果还有对象的时候,Object.freeze()失效了。

2.2、深冻结

var obj = {
    name: '张三',
    info: {
        a: 1,
        b: 2
    }
}

function deepFreeze(obj) {
    // 获取所有属性
    var propNames = Object.getOwnPropertyNames(obj)
 
    // 遍历
    propNames.forEach(item => {
        var prop = obj[item]
        // 如果某个属性的属性值是对象,则递归调用
        if (prop instanceof Object && prop !== null) {
            deepFreeze(prop)
        }
    })

    // 冻结自身
    return Object.freeze(obj)
}

deepFreeze(obj)

obj.name = '李四'
console.log(obj)    // {name: "张三", info: {…}}

obj.info.a = 100
console.log(obj.info)   // {a: 1, b: 2}

3、应用场景

Object.freeze()可以提高性能,如果你有一个对象,里面的内容特别特别多,而且都是一些静态数据,你确保不会修改它们,那你其实可以用Object.freeze()冻结起来,这样可以让性能大幅度提升,提升的效果随着数据量的递增而递增。对于纯展示的大数据,都可以使用Object.freeze提升性能。

4、Vue中使用Object.freeze

在vue项目中,data初始化 里面一般会有很多变量,后续如果不想使用它,可以使用Object.freeze()。这样可以避免vue初始化时候,做一些无用的操作,从而提高性能。

data(){
    return{
        list:Object.freeze({'我不需要改变'})
    }
}

注意:被冻结的对象无法解冻,此方法无法逆转

二、Object.isFrozen()

Object.isFrozen()  静态方法判断一个对象是否被冻结。

三、Object.assign()方法或展开语法(…)来合并对象

在JavaScript中,你可以使用Object.assign()方法或者使用Spread Operator (…) 来合并对象。

1、Object.assign()

Object.assign() 静态方法将一个或者多个源对象中所有可枚举的自有属性复制到目标对象,并返回修改后的目标对象。

1.1、语法

Object.assign(target, ...sources)

1.2、参数

  • target:需要应用源对象属性的目标对象,修改后将作为返回值。
  • sources:一个或多个包含要应用的属性的源对象。

示例

let name = { name:'sea' },age = { age:15 },person= {}

Object.assign(person,name,age)

console.log(person) 
//{ name:'sea',age:15 }

在这个例子中,Object.assign()方法创建了一个新的对象,其属性是所有传入对象的属性的拷贝。

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

const returnedTarget = Object.assign(target, source);

console.log(target);
// Expected output: Object { a: 1, b: 4, c: 5 }

console.log(returnedTarget === target);
// Expected output: true

如果目标对象与源对象具有相同的键(属性名),则目标对象中的属性将被源对象中的属性覆盖,后面的源对象的属性将类似地覆盖前面的源对象的同名属性。

2、展开语法Spread Operator (…)

浅拷贝 (Shallow-cloning,不包含 prototype) 和对象合并,可以使用更简短的展开语法。而不必再使用 Object.assign() 方式。

Spread运算符也可以用来合并对象。它可以将一个数组或对象展开到一个函数或数组中。

let name = { name:'sea' },age = { age:15 }

let person = { ...name,...age }

console.log(person)
//{ name:'sea',age:15 }

在这个例子中,Spread Operator (…) 用于扩展对象,所以它复制了所有对象的属性到新的对象中。

var obj1 = { foo: "bar", x: 42 };
var obj2 = { foo: "baz", y: 13 };

var clonedObj = { ...obj1 };
// 克隆后的对象:{ foo: "bar", x: 42 }

var mergedObj = { ...obj1, ...obj2 };
// 合并后的对象:{ foo: "baz", x: 42, y: 13 }

3、区别

Object.assign() 函数会触发 setters,而展开语法则不会。