好用的 JavaScript Symbol 类型
声明定义symbol的几种方式:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <script> // let a = Symbol(); // let b = Symbol(); // console.log(a); // console.log(typeof a); // console.log(a == b); // Symbol可以加上描述 // let a = Symbol('这是a'); // console.log(a); // console.log(a.toString()); // console.log(a.description); // Symbol() 和Symbol.for() 的区别 // let a = Symbol('cyy'); // let b = Symbol('cyy'); // console.log(a == b); // Symbol.for是在全局存储一个变量,可以使用Symbol.keyFor来获取到描述 // Symbol()没有,不能获取到描述 // let a2 = Symbol.for('cyy'); // let b2 = Symbol.for('cyy'); // console.log(a2 == b2); // console.log(Symbol.keyFor(a2)); </script> </body> </html>
使用Symbol解决字符串耦合问题:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <style> </style> </head> <body> <script> // 前面的cyy属性被后面的覆盖 // let grade = { // cyy: { // class: 'html', // score: 99 // }, // cyy2: { // class: 'css', // score: 28 // }, // cyy: { // class: 'html', // score: 33 // }, // }; // console.log(grade); // let user1 = 'cyy1'; // let user2 = 'cyy2'; // let grade = { // user1: { // class: 'html', // score: 99 // }, // user2: { // class: 'css', // score: 28 // }, // }; // console.log(grade); // 属性名需要加上中括号才能使用变量 // let user1 = 'cyy1'; // let user2 = 'cyy2'; // let grade = { // [user1]: { // class: 'html', // score: 99 // }, // [user2]: { // class: 'css', // score: 28 // }, // }; // console.log(grade); let user1 = { name: 'cyy1', key: Symbol() }; let user2 = { name: 'cyy2', key: Symbol() }; let grade = { [user1.key]: { class: 'html', score: 99 }, [user2.key]: { class: 'css', score: 28 }, }; console.log(grade); console.log(grade[user1.key]); console.log(grade[user2.key]); </script> </body> </html>
Symbol在缓存容器中的使用:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <style> </style> </head> <body> <script> class Cache { static data = {}; static set(name, value) { return this.data[name] = value; } static get(name) { return this.data[name]; } } // Cache.set('cyy', 'girl'); // console.log(Cache.get('cyy')); // 存在覆盖的情况 // let user = { // name: 'apple', // desc: '用户' // }; // let cart = { // name: 'apple', // desc: '购物车' // }; // Cache.set('apple', user); // Cache.set('apple', cart); // console.log(Cache.get('apple')); // 传统解决方法 // let user = { // name: 'apple', // desc: '用户' // }; // let cart = { // name: 'apple', // desc: '购物车' // }; // Cache.set('user-apple', user); // Cache.set('cart-apple', cart); // console.log(Cache.get('user-apple')); let user = { name: 'apple', desc: '用户', key: Symbol() }; let cart = { name: 'apple', desc: '购物车', key: Symbol() }; Cache.set(user.key, user); Cache.set(cart.key, cart); console.log(Cache.get(user.key)); </script> </body> </html>
扩展特性与对象属性保护:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <style> </style> </head> <body> <script> // Symbol的对象属性保护,无法使用for-of或者for-in来循环遍历 // let symbol = Symbol('这是一个symbol类型'); // let obj = { // name: 'cyy', // [symbol]: 'cyy-symbol' // }; // for (let o of obj) { // console.log(o); // } // for (let k in obj) { // console.log(k); // } // for (let k of Object.keys(obj)) { // console.log(k); // } // 只遍历symbol属性 // for (let k of Object.getOwnPropertySymbols(obj)) { // console.log(k); // } // 遍历所有属性 // for (let k of Reflect.ownKeys(obj)) { // console.log(k); // } // 对象属性保护,不希望让外界获取到的属性 let secret = Symbol('这是我的小秘密~'); class User { // 构造函数 constructor(name) { this.name = name; this[secret] = '保密'; } getName() { return `${this.name}--${this[secret]}`; } } let c = new User('cyy呀'); console.log(c.getName()); for (let k in c) { console.log(k); } </script> </body> </html>
补充一下
Reflect.ownKeys()与Object.keys()区别
var obj = {
a: 1,
b: 2
}
Object.defineProperty(obj, 'method', {
value: function () {
alert("Non enumerable property")
},
enumerable: false
})
console.log(Object.keys(obj))
// ["a", "b"]
console.log(Reflect.ownKeys(obj))
// ["a", "b", "method"]
从结果上看出:
Object.keys()返回属性key,但不包括不可枚举的属性
Reflect.ownKeys()返回所有属性key
Object.keys() : 相当于返回属性数组
Reflect.ownKeys() :相当于Object.getOwnPropertyNames(target) concat(Object.getOwnPropertySymbols(target)
getOwnPropertyNames():方法: 返回所有属性的数组
Object.getOwnPropertySymbols():方法: 返回所有符号属性直接发现在给定的对象