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

相关推荐
C_心欲无痕25 分钟前
前端实现文件下载的完整流程
前端·状态模式
Fighting_p30 分钟前
【element UI】el-select 组件下拉数据某一行文字过多时,文字换行展示,避免el-select下拉框被撑宽,导致页面过丑
前端·javascript
王家视频教程图书馆38 分钟前
vue3从本地选择一个视频 展示到视频组件中
前端·javascript·音视频
天外来鹿1 小时前
Map/Set/WeakMap/WeakSet学习笔记
前端·javascript·笔记·学习
Luna-player1 小时前
前端中stylus是干嘛用的
前端·css·stylus
CHQIUU1 小时前
解决 npm 全局安装 EACCES 权限问题(macOS 篇)
前端·macos·npm
程序员鱼皮1 小时前
OpenClaw接入飞书保姆级教程,几分钟搞定手机养龙虾!
前端·人工智能·后端
紫_龙2 小时前
最新版vue3+TypeScript开发入门到实战教程之vue3与vue2语法优劣对比
前端·javascript·typescript
SouthRosefinch2 小时前
一、HTML简介与开发环境
开发语言·前端·html
全栈小52 小时前
【前端】Vue 组件开发中的枚举值验证:从一个Type属性错误说起
前端·javascript·vue.js