隐藏才Symbol角落中的那些属性

tech2022-07-04  156

1.介绍

Symbol–ES6新加入了一种原始数据类型平时对Symbol的使用可能就是利用它表示独一无二的值的特性,作为对象的key,或者那些强耦合的字符串,比如vuex时定义的mutation-type等但是还有很多属性没有被我们看到,我们打印一下Symbol看看

1、其实很多方法底层都是调用的Symbol的这些属性

比如我们看到的 replace、search、split 这些属性 当String调用原型上相应的方法时,其实就是调用的Symbol对应的属性。

2、除了String的那些方法、还有一些常见的方法都是调用了Symbol的属性,比如使用instanceof 判断类型时,调用了Symbol.hasInstance属性。

我们先打印一下对象的原型可以看到,是存在这个属性的

class A{}; let a = new A(); console.log(a instanceof A); console.log(A[Symbol.hasInstance](a)); //结果为 //true true

3、数组的Array.prototype.concat()方法调用了Symbol.isConcatSpreadable(一个Boolean型)来判断是否展开数组

let arr = [1,2,3]; let arr2 = [4,5,6]; arr[Symbol.isConcatSpreadable] = false; console.log(arr2.concat(arr)); //结果如下 可以看到 arr就不会被展开了

4、迭代数组等数据结构时,通过Symbol.iterator判断是否可以迭代

//我们知道只有实现了Symbol.iterator的数据才可以被for of迭代 array、set、map 都默认实现了接口 我们要想让我们自己写的类数组 也可以被for of 迭代的话,我们就要自己实现它 //当我们没有实现时 let a = { 0:"aa", 1:"12", length:2 } //会报错 Uncaught TypeError: a is not iterable let a = { 0:"aa", 1:"12", length:2, [Symbol.iterator]: Array.prototype[Symbol.iterator] } //把数组的实现赋给[Symbol.iterator] 便可以遍历了 //****************************************** //如果想让对象可遍历,我们可以自己实现一个iterator let a = { a:"aa", b:"12", } a[Symbol.iterator] = function(){ let i = 0; let keys = Object.keys(a); return{ next(){ let done = (i >= a.length); let value = !done ? a[keys[i++]] : undefined; return{ value, done } } } }

5、当一个对象被转换为原始类型值时调用Symbol.toPrimitive

比如 == 进行的数据类型转换,或者 + 两边有一方为字符串 另一个进行数据类型转换 比如 123 + '4'

let a = {}; a[Symbol.toPrimitive] = function(hint) { switch (hint) { case 'number': //此时需要转换成数值 return 1000; case 'string': // 此时需要转换成字符串 return String("1000"); case 'default': //此时可以转换成数值或字符串 return 1000; } } if (a+"" === "1000") { console.log('OK1'); } //输出 OK1

6、当调用对象原型的toString方法时调用Symbol.toStringTag

class A{ get [Symbol.toStringTag]() { return "A"; } } let a= new A; console.log(Object.prototype.toString.call(a)); //"[object A]" //这样就可以返回对象对应的类了 如果有错误 请及时指出 以免误导更多的同学!
最新回复(0)