Symbol模拟实现

本文详细探讨了Symbol类型在JavaScript中的作用,以及如何通过JavaScript原生API和基本概念来模拟实现Symbol的功能。通过对Symbol的创建、特性及用途的解析,揭示其在防止属性名冲突、创建不可枚举属性等方面的关键价值。
摘要由CSDN通过智能技术生成
<!-- 

当调用 Symbol 的时候,会采用以下步骤:

1 如果使用 new ,就报错
2 如果 description 是 undefined,让 descString 为 undefined
3 否则 让 descString 为 ToString(description)
4 如果报错,就返回
5 返回一个新的唯一的 Symbol 值,它的内部属性 [[Description]] 值为 descString
考虑到还需要定义一个 [[Description]] 属性,如果直接返回一个基本类型的值,是无法做到这一点的,所以我们最终还是返回一个对象。

为了防止不会出现同名的属性,毕竟这是一个非常重要的特性,迫不得已,我们需要修改 toString 方法,
让它返回一个唯一值,所以第 8 点就无法实现了,而且我们还需要再写一个用来生成 唯一值的方法,就命名为 generateName,我们将该唯一值添加到返回对象的 __Name__ 属性中保存下来

7.Symbol 值不能与其他类型的值进行运算,会报错。

以 + 操作符为例,当进行隐式类型转换的时候,会先调用对象的 valueOf 方法,如果没有返回基本值,就会再调用 toString 方法,所以我们考虑在 valueOf 方法中进行报错,比如:


10. Symbol 作为属性名,该属性不会出现在 for...in、for...of 循环中,也不会被 Object.keys()、Object.getOwnPropertyNames()、JSON.stringify() 返回。但是,它也不是私有属性,有一个 Object.getOwnPropertySymbols 方法,可以获取指定对象的所有 Symbol 属性名。

嗯,无法实现。

11. 有时,我们希望重新使用同一个Symbol值,Symbol.for方法可以做到这一点。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值。

这个实现类似于函数记忆,我们建立一个对象,用来储存已经创建的 Symbol 值即可。

12. Symbol.keyFor 方法返回一个已登记的 Symbol 类型值的 key。

遍历 forMap,查找该值对应的键值即可。
-->
<script>
    (function() {
        var root = this;
        var generateName = (function() {
            var postfix = 0;
            return function(descString) {
                postfix++;
                return `@@${descString}_${postfix}`;
            }
        })();

        var forMap = {};
        var SymbolPolyfill = function Symbol(description) {
            if (this instanceof SymbolPolyfill) {
                throw new TypeError("Symbol is not a constructor");
            }

            var descString = description === undefined ? undefined : description;

            var symbol = Object.create({
                toString: function() {
                    return this.__Name__;
                },
                valueOf: function() {
                    throw new Error("Cannot convert a Symbol value");
                }
            });

            Object.defineProperties(symbol, {
                "__Description__": {
                    value: descString,
                    writable: false,
                    enumerable: false,
                    configurable: false
                },

                "__Name__": {
                    value: generateName(descString),
                    writable: false,
                    enumerable: false,
                    configurable: false
                }
            })

            return symbol;
        }

        Object.defineProperties(SymbolPolyfill, {
            'for': {
                value: function(description) {
                    var descString = description === undefined ? undefined : String(description)
                    return forMap[descString] ? forMap[descString] : forMap[descString] = SymbolPolyfill(descString);
                },
                writable: true,
                enumerable: false,
                configurable: true
            },
            'keyFor': {
                value: function(symbol) {
                    for (var key in forMap) {
                        if (forMap[key] === symbol) return key;
                    }
                },
                writable: true,
                enumerable: false,
                configurable: true
            }
        })

        root.SymbolPolyfill = SymbolPolyfill;
    })();
    console.log(SymbolPolyfill(1))
    console.log(SymbolPolyfill(1).toString());
    console.log(String(SymbolPolyfill(1)));

    var a = SymbolPolyfill('foo');
    var b = SymbolPolyfill('foo');

    console.log(a === b); // false

    var o = {};
    o[a] = 'hello';
    o[b] = 'hi';

    console.log(o); // Object { "@@foo_1": "hello", "@@foo_2": "hi" }

    console.log('1' + symbol); // 报错
</script>
博客
v8worker
05-08 2892
05-06 2871
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值