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 可以提供一些有用的功能,但它们也会增加代码的复杂性,所以在不需要的情况下,最好避免使用它们。

相关推荐
顾安r3 小时前
11.8 脚本网页 星际逃生
c语言·前端·javascript·flask
Hello.Reader3 小时前
Data Sink定义、参数与可落地示例
java·前端·网络
im_AMBER4 小时前
React 17
前端·javascript·笔记·学习·react.js·前端框架
谷歌开发者5 小时前
Web 开发指向标 | Chrome 开发者工具学习资源 (六)
前端·chrome·学习
一晌小贪欢5 小时前
【Html模板】电商运营可视化大屏模板 Excel存储 + 一键导出(已上线-可预览)
前端·数据分析·html·excel·数据看板·电商大屏·大屏看板
发现你走远了5 小时前
连接模拟器网页进行h5的调试(使用Chrome远程调试(推荐)) 保姆级图文
前端·chrome
街尾杂货店&6 小时前
css - 实现三角形 div 容器,用css画一个三角形(提供示例源码)简单粗暴几行代码搞定!
前端·css
顺凡6 小时前
删一个却少俩:Antd Tag 多节点同时消失的原因
前端·javascript·面试
小白路过6 小时前
CSS transform矩阵变换全面解析
前端·css·矩阵
爬山算法6 小时前
Redis(110)Redis的发布订阅机制如何使用?
前端·redis·bootstrap