不才,只能参考的是网络上的博客和素材。

Symbol类型持有特性

1-类型是symbol,可通过typeof关键字去取的

  1. let s = Symbol();
  2. typeof s; // "symbol"

2-不能使用new执行,所以instanceof 结果是false

因为生成的Symbol是个原始类型的值,不是对象

  1. let s = Symbol();
  2. s instanceof Symbol; // false

3-Symbol函数接受一个字符串作为参数,表示对Symbol实例的描述

  1. let s = Symbol("str");
  2. console.log(s); // Symbol(str)

4-如果Symbol的参数是对象,就调用该对象的toString(),转为字符串后,才生成一个Symbol值

  1. const obj = {
  2. toString() {
  3. return "abc";
  4. }
  5. }
  6. let s = Symbol(obj);
  7. console.log(s); // Symbol(abc)

5-值是唯一的,无论是传相同的参数还是不传参

  1. // 没有参数
  2. let s1 = Symbol();
  3. let s2 = Symbol();
  4. s1 === s2; // false
  5. // 相同参数
  6. let s3 = Symbol("str");
  7. let s4 = Symbol("str");
  8. s3 === s4; // false

6-不能与其他类型进行运算,会报错

  1. let s = Symbol("str");
  2. "my" + s; // Uncaught TypeError:Cannot convert a Symbol value to a string

7-显示可以转为字符串

  1. let s = Symbol("str");
  2. String(s); // Symbol(str)
  3. s.toString(s); // Symbol(str)

8-Symbol 值可以作为标识符,用于对象的属性名,可以保证不会出现同名的属性

  1. let s = Symbol();
  2. // 第一种写法
  3. let a = {};
  4. a[s] = "hello";
  5. // 第二种写法
  6. let a = {
  7. [s]: "hello"
  8. };
  9. // 第三种写法
  10. let a = {};
  11. Object.defineProperty(a, s, {value: "hello"});
  12. // 以上都是同样的结果
  13. a[s]; // "hello"

9-Symbol作为属性名,不会出现在for…in,for…of,Object.keys(),Object.getOwnPropertyNames(),JSON.stringify()返回,只有Object.getOwnPropertySymbols方法可以返回

  1. let obj = {};
  2. let a1 = Symbol("a");
  3. let b1 = Symbol("b");
  4. obj[a1] = "hello";
  5. obj[b1] = "world";
  6. console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(a), Symbol(b)]

10-如果我们希望使用同一个Symbol值,可以用Symbol.for(),接受一个字符串作为参数,搜索有没有该参数做为名称的Symbol值,有就返回这个值,否则就新建

  1. let s1 = Symbol.for("str");
  2. let s2 = Symbol.for("str");
  3. s1 === s2; // true

11-Symbol.keyFor()返回一个已登记的Symbol类型值的key

  1. let s1 = Symbol.for("str");
  2. console.log(Symbol.keyFor(s1)); // "foo"
  3. let s2 = Symbol("str");
  4. console.log(Symbol.keyFor(s2)); // undefined

实现

  1. (function() {
  2. var root = this;
  3. // 9-作为标识符,可用于对象属性名,而且唯一性
  4. var generateName = (function(){
  5. var postfix = 0;
  6. return function(descString) {
  7. postfix++;
  8. return "@@" + descString + "_" + postfix
  9. }
  10. })();
  11. var SymbolPolyfill = function Symbol(description) {
  12. // 2-不能调用new命令
  13. // 3-instanceof结果为false,因为不能通过new的方式实现
  14. if(this instanceof SymbolPolyfill) throw new TypeError("Symbol is not a constructor");
  15. // 5-参数是个对象就转成字符串
  16. var descString = description === undefined undefined : String(description);
  17. var symbol = Object.create({
  18. toString: function() {
  19. return this._Name_;
  20. },
  21. // 6-不能与其它类型的值进行运算
  22. // 以+操作符为例,当进行隐式类型转换的时候,会先调用对象的valueOf方法,如果没有返回基本值,
  23. // 就会再调用toString方法,所以要在valueOf方法中进行报错
  24. valueOf: function() {
  25. throw new Error("Cannot convert a Symbol value");
  26. }
  27. });
  28. Object.definedProperties(symbol, {
  29. '_Description_' : {
  30. value: descString,
  31. writable: false,
  32. enumerable: false,
  33. configurable: false
  34. },
  35. '_Name_': {
  36. value: generateName(descString),
  37. writable: false,
  38. enumerable: false,
  39. configurable: false
  40. }
  41. });
  42. // 6-返回一个新对象,只要引用不同,就不会相同
  43. return symbol;
  44. }
  45. var forMap = {};
  46. Object.defineProperties(SymbolPolyfill, {
  47. // 10-希望重新使用相同一个Symbol值,利用Symbol.for()传入一个参数,有就返回,否则新建
  48. // 类似函数记忆,建立一个对象,用来存储已经创建的Symbol值
  49. 'for': {
  50. value: function(description) {
  51. var descString = description === undefined ? undefined : String(description)
  52. return forMap[descString] ? forMap[descString] : forMap[descString] = SymbolPolyfill(descString);
  53. },
  54. writable: true,
  55. enumerable: false,
  56. configurable: true
  57. },
  58. // 11-Symbol.keyFor()方法返回一个已登记的Symbol类型的key
  59. // 遍历forMap,查找该值对应的键值即可
  60. 'keyFor': {
  61. value: function(symbol) {
  62. for (var key in forMap) {
  63. if (forMap[key] === symbol) return key;
  64. }
  65. },
  66. writable: true,
  67. enumerable: false,
  68. configurable: true
  69. }
  70. });
  71. root.SymbolPolyfill = SymbolPolyfill;
  72. }())

1-typeof,结果为”symbol”
不能实现,并不能修改typeof操作符
4-在控制台显示Symbol实例的时候,显示字符串
不能实现,模拟的是对象,无法通过调用原生console.log()打印出字符串
7-Symbol值显式转为字符串
不能实现,因为在实现上存在第8点冲突了,模拟的所谓Symbol值其实是一个有着toString方法的对象,当对象作为对象属性名的时候,进行了隐式类型转换,还是会调用toString方法,出现相同的属性名;为了不会出现相同的属性名,要返回的是一个唯一值,需要修改toString方法,就命名为 generateName,我们将该唯一值添加到返回对象的 Name 属性中保存下来
9-里面的遍历属性的方法
不能实现

微信公众号:**游戏机室
qrcode_for_gh_0e7f620a68c0_258.jpg**