终于在实战中用上Symbol

问:Symbol,究竟有什么作用
答:面试时有用,作为js的其中一种基本类型

真正的使用场景其实在网上一搜,也有很多答案,无非是
1.模拟私有属性
2.防止对象属性值命名冲突
3.xxx

一般来说,写业务很少会利用到这特性,而很多第三方工具(框架类库)都有用到,例如React的$$typeof属性用到Symbol,作用是防止xss(因为数据库无法存储Symbol),所以说React是天然防xss的

场景

终于有一天,在开发一个第三方工具(组件)时,想到Symbol可以帮我解决一个难题,场景是这样
1.这组件是依赖antd4.x的Form
2.它能通过数组格式配置生成表单控件,可以配置联动效果

// 数据模型
const config = [
  {
    label: '姓名',
    name: 'name',
    depChange: values => {
      if (values.sex === 1) {
        return '男姓名';
      }
    },
    placeholder: '性别选择男看看效果',
  },
  {
    label: '性别',
    name: 'sex',
    type: 'select',
    options: [
      { label: '男', value: 1 },
      { label: '女', value: 2 },
    ],
  }
];

简单描述下,depChange作用就是当表单值变化时执行,性别(sex)值为女(1)时,姓名的值自动变成“男姓名”, 实现思路是利用Fom的onValuesChange,将config配置的所有depChange依次执行(onValuesChanges的changedValues作参数),并装在一个deps对象里,最后setFieldsValue(deps)达到值更新效果

然而

当性别选择男时,姓名自动变成“男姓名”,然后在姓名打上任意字符,会发现,值清空了,为什么呢,列举一下步骤:
1.选择性别“男”,姓名自动填充为“男姓名” (正常)
2.姓名上输入1,姓名自动变成“空” (异常,理想是变成“男姓名1”)

why?

因为第二部的changedValues为

{name: "男姓名1"}

再看看姓名的depChanges配置

   depChange: values => {
     if (values.sex === 1) {
       return '男姓名';
     }
  }

执行后会返回undefined!这是函数默认的返回结果!这可是一个棘手的问题,我可不想将姓名重置的,只是函数会默认返回undefined

解决

将函数默认返回值改成Symbol

      for (let k in dependence) {
        const actionStr = dependence[k].action.toString();

        // 函数劫持,拿return Symbol兜底
        const i = actionStr.lastIndexOf('}');
        const code =
          actionStr.slice(0, i) + `return Symbol()` + actionStr.slice(i);

        const newFunc = new Function(`return ${code}`)();

        let v = newFunc(changedValues);
        // 返回Symbol的不收集
        if (typeof v !== 'symbol') {
          deps[k] = v;
        }
      }

将函数劫持重写最后返回"return Symbol()",这样就避免了默认值是undefined,后面会判断当返回值是非symbol类型l时才执行联动函数,避免清空的情况

为什么

Q:为什么用Symbol,而不用其他数据类型
A:因为你不能将Symbol输入到实际的控件值中,暂时没看到有控件支持,业务逻辑上也走不通

你可能感兴趣的:(终于在实战中用上Symbol)