Javascript 中的 Symbol 属性

还记得我在Lodash专栏深拷贝部分提到的Symbol属性吗?它是ES6引入的一种新的原始数据类型,表示独一无二的值。你可以使用Symbol来创建对象的唯一属性键。我们往往希望创建私有属性,或者向第三方对象动态添加属性(防止属性名冲突)的时候,会使用Symbol。 另外,javascript中还提供了一些与定语的Symbol值,称为 Well-know Symbols,如Symbol.iteratorSymbol.toStringTag等。

以下是一个使用Symbol定义对象属性的例子:

javascript 复制代码
let symbolKey = Symbol('key');
let obj = {};

obj[symbolKey] = 'value';
console.log(obj[symbolKey]); // 输出 'value'

在这个例子中,我们创建了一个symbolKey作为obj的属性键。你可以看到,这个属性的键是独一无二的,并且不会与obj的其他属性产生冲突。我们称这样的属性为Symbol属性。

当我们说 "克隆对象的符号属性" 时,我们是指复制对象的所有 Symbol 类型的属性键及其对应的值。

Symbol 属性在前端工程中的使用场景

Symbol 类型的属性键在 JavaScript 中的使用并不是非常常见,但在某些特定的场景下,它们可以提供很大的帮助。以下是一些可能的使用场景:

  1. 创建私有属性 :在 JavaScript 中,对象的所有属性都是公开的,任何代码都可以访问和修改它们。然而,有时我们可能希望创建一些私有属性,只能通过对象的方法来访问和修改。Symbol 可以帮助我们实现这一点,因为 Symbol 类型的属性键不能被常规的遍历操作(如 for...in 循环、Object.keys 方法等)访问到。

    javascript 复制代码
    const privateProperty = Symbol('privateProperty');
    
    const createMyObject = () => {
        const obj = {};
        obj[privateProperty] = 'This is private';
    
        obj.getPrivateProperty = function() {
            return this[privateProperty];
        };
    
        return obj;
    }
    
    const instance = createMyObject();
    console.log(instance.getPrivateProperty()); // 'This is private'
    console.log(Object.keys(instance)); // ['getPrivateProperty'],私有属性不会被遍历到

这里我们复习下 this 指向性的问题。

this 关键字的值取决于函数的调用方式。在 createMyObject 函数中,thisgetPrivateProperty 方法中被使用。

javascript 复制代码
obj.getPrivateProperty = function() {
    return this[privateProperty];
};

在这个例子中,getPrivateProperty 是作为 obj 对象的一个方法被定义的。当一个函数作为对象的方法被调用时,this 通常指向调用该方法的对象。因此,当我们调用 instance.getPrivateProperty() 时,thisgetPrivateProperty 方法中指向 instance 对象。

javascript 复制代码
const instance = createMyObject();
console.log(instance.getPrivateProperty()); // 'This is private'

在这个调用中,this[privateProperty] 就等同于 instance[privateProperty],因此它返回的是 instance 对象的私有属性的值。

需要注意的是,this 的值并不是在函数定义时确定的,而是在函数调用时确定的。如果我们以不同的方式调用 getPrivateProperty 方法,this 的值可能会不同。例如,如果我们直接调用 getPrivateProperty 函数,而不是作为 instance 的方法调用它,那么 this 就会指向全局对象(在浏览器中是 window 对象,在 Node.js 中是 global 对象)。

javascript 复制代码
const getPrivateProperty = instance.getPrivateProperty;
console.log(getPrivateProperty()); // undefined,因为 this 指向全局对象,全局对象没有 privateProperty 属性

这就是为什么我们通常需要小心处理 this 的值,特别是在事件处理器和回调函数中。在这些情况下,我们可能需要使用 bindcallapply 方法来显式地设置 this 的值。

  1. 防止属性名冲突:如果你正在编写一个库或框架,你可能需要向用户提供的对象添加一些属性。使用 Symbol 类型的属性键可以防止你添加的属性与用户的属性发生冲突。

    javascript 复制代码
    const libraryProperty = Symbol('libraryProperty');
    
    function enhanceObject(obj) {
        obj[libraryProperty] = 'Enhanced by library';
        // 添加其他属性和方法...
        return obj;
    }
  2. 使用 Well-known Symbols :JavaScript 提供了一些预定义的 Symbol 值,称为 Well-known Symbols,如 Symbol.iteratorSymbol.toStringTag 等。这些 Symbol 值在 JavaScript 的内部机制中有特殊的用途。例如,你可以使用 Symbol.iterator 来定义一个对象的默认迭代行为。

    javascript 复制代码
    const myIterable = {
        [Symbol.iterator]: function* () {
            yield 1;
            yield 2;
            yield 3;
        }
    };
    
    for (let value of myIterable) {
        console.log(value); // 1, 然后 2, 然后 3
    }

以上就是一些在前端业务中可能会使用到 Symbol 类型的属性键的场景。然而,需要注意的是,虽然 Symbol 可以提供一些有用的功能,但它们也会增加代码的复杂性,所以在不需要的情况下,最好避免使用它们。

相关推荐
UI前端开发工作室24 分钟前
数字孪生技术为UI前端提供新视角:产品性能的实时模拟与预测
大数据·前端
Sapphire~27 分钟前
重学前端004 --- html 表单
前端·html
遇到困难睡大觉哈哈1 小时前
CSS中的Element语法
前端·css
Real_man1 小时前
新物种与新法则:AI重塑开发与产品未来
前端·后端·面试
小彭努力中1 小时前
147.在 Vue3 中使用 OpenLayers 地图上 ECharts 模拟飞机循环飞行
前端·javascript·vue.js·ecmascript·echarts
老马聊技术1 小时前
日历插件-FullCalendar的详细使用
前端·javascript
咔咔一顿操作1 小时前
Cesium实战:交互式多边形绘制与编辑功能完全指南(最终修复版)
前端·javascript·3d·vue
LuckyLay2 小时前
使用 Docker 搭建 Rust Web 应用开发环境——AI教你学Docker
前端·docker·rust
pobu1683 小时前
aksk前端签名实现
java·前端·javascript
烛阴3 小时前
带参数的Python装饰器原来这么简单,5分钟彻底掌握!
前端·python