-
Notifications
You must be signed in to change notification settings - Fork 0
/
Symbol.html
301 lines (282 loc) · 11 KB
/
Symbol.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<h1> Symbol</h1>
1. 保证每个属性名称都是独一无二的
由原来的6种数据结构 undefined null Boolean String Number Object
扩展一个Symbol
</br>
let s=Symbol()</br>
console.log(typeof s)
//symbol </br></br></br>
<script>
let demo1=Symbol()
console.log("demo1"+typeof demo1)
</script>
2. Symbol前不能使用new 会报错 它是类似字符串的数据类型 无法添加属性</br>
Symbol函数可以接受一个字符串作为参数 主要来描述Symbol实例 在控制台种能够区分</br>
如果参数事对象 就会调用对象的toString方法 生成一个Symbol</br>
即使两个参数相同Symbol的返回值也是不相等的</br>
Symbol值不能与其他值进行运算 会报错 console.log("string"+symbol) 都会报错</br>
可以显式的转成字符串</br>
可以转成布尔值,但不能转为数值(Number(stmbol)//会报错)</br>
const obj = {</br>
toString() {</br>
return 'abc';</br>
}</br>
};</br>
let s1 = Symbol('foo');</br>
s1.toString() // "Symbol(foo)"</br>
const sym = Symbol(obj);</br>
sym // Symbol(abc)</br></br></br>
3.作为属性名的symbol基础用法 不能使用.运算符(例如xx.mySymbol ) let symbol = Symbol('size')typeof this[symbol] 为值 typeof size 为 symbol 注意 .后面只能接字符串
用于对象的属性,保证不会出现相同的属性</br>
命名方式</br>
let mySymbol=Symbol()</br>
//第一种</br>
let a={}</br>
a[mySymbol]='hello'</br>
//第二种</br>
let a={</br>
[mySymbol]:'hello'</br>
}</br>
//第三种</br>
let a={};</br>
Object.defineProperty(a,mySymbol,{value:'hello'})</br>
//demo 使用.运算符的结果
const mySymbol=Symbol();</br>
demo3.mySymbol='hello122'</br>
console.log("demo3"+demo3.mySymbol+"----"+typeof demo3.mySymbol)//demo3hello122----string</br>
console.log("demo3"+demo3[mySymbol]+"----"+typeof demo3[mySymbol] )//demo3undefined----undefined</br>
console.log("demo3"+demo3['mySymbol']+"----"+typeof demo3['mySymbol'])//demo3hello122----string</br>
</br></br></br>
<script>
let mySymbol=Symbol()
//第一种
let a={}
a[mySymbol]='hello'
//第二种
// let a={
// [mySymbol]:'hello'
// }
//第三种
// let a={};
// Object.defineProperty(a,mySymbol,{value:'hello'})
console.log(a[mySymbol])
let demo3={};
demo3.mySymbol='hello122'
console.log("demo3"+demo3.mySymbol+"----"+typeof demo3.mySymbol)
console.log("demo3"+demo3[mySymbol]+"----"+typeof demo3[mySymbol] )
console.log("demo3"+demo3['mySymbol']+"----"+typeof demo3['mySymbol'])
</script>
4 如何取值 </br>
4.1 不会出现在for...in,for...of循环种也不会Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回,</br>
4.2 同时也不是私有属性(Object.getOwnPropertyNames(obj)获取不到),有一个Object.getOwnPropertySymbols方法,可以获取指定对象的所有 Symbol 属性名。</br>
4.3 Reflect.ownKeys(obj4) 可以获取obj4种的所有symbol值(数组) </br>
4.4 由于以 Symbol 值作为名称的属性,不会被常规方法遍历得到。我们可以利用这个特性,为对象定义一些非私有的、但又希望只用于内部的方法。 </br>
let obj4={}</br>
let a4=Symbol('a')</br>
let b4=Symbol('b')</br>
obj4[a4]='hello';</br>
obj4[b4]='world'</br>
let objSymbol4=Object.getOwnPropertySymbols(obj4)</br>
console.log(Reflect.ownKeys(obj4))//[Symbol(a), Symbol(b)]</br>
4.4
let x = new Collection();</br>
Collection.sizeOf(x) // 0</br>
x.add('foo');</br>
console.log(Collection.sizeOf(x)) // 1</br>
console.log( Object.keys(x) )// ['0']</br>
console.log( Object.getOwnPropertyNames(x) ) // ['0']</br>
console.log( Object.getOwnPropertySymbols(x) )//[Symbol(size)]</br>
<script>
let obj4={}
let a4=Symbol('a')
let b4=Symbol('b')
obj4[a4]='hello';
obj4[b4]='world'
let objSymbol4=Object.getOwnPropertySymbols(obj4)
objSymbol4.forEach((item)=>{
console.log(item);
})
console.log(Reflect.ownKeys(obj4))//[Symbol(a), Symbol(b)]
let size = Symbol('size');
class Collection {
constructor() {
this[size] = 0;
}
add(item) {
this[this[size]] = item;
this[size]++;
}
static sizeOf(instance) {
return instance[size];
}
}
</script>
5 </br>
Symbol() 调用30个会返回30个</br>
Symbol.for() 会生成新的Symbol在全局中 如果存在则不创建,会返回那个 如果不存在则创建 调用30次只会返回一个 都相同</br>
Symbol.keyFor() 参数是Symbol类型不是key 返回已登记的 Symbol 类型值的key。 查找 Symbol.for()注册的 symbol的不算是</br>
demo</br>
let temp5=Symbol('temp5')</br>
let temp5_1=Symbol('temp5')</br>
Symbol.keyFor(temp5)//undefined</br>
let temp5_2=Symbol.for('temp5')</br>
let temp5_3=Symbol.for('temp5')</br>
Symbol.keyFor(temp5_2)//temp5</br>
console.log(temp5==temp5_1)//false</br>
console.log(temp5_1==temp5_2)//false</br>
console.log(temp5==temp5_2)//false</br>
console.log(temp5_2==temp5_3)//true</br></br></br>
<script>
let temp5=Symbol('temp5')
let temp5_1=Symbol('temp5')
Symbol.keyFor(temp5)//undefined
let temp5_2=Symbol.for('temp5')
let temp5_3=Symbol.for('temp5')
Symbol.keyFor(temp5_2)//temp5
console.log(temp5==temp5_1)//false
console.log(temp5_1==temp5_2)//false
console.log(temp5==temp5_2)//false
console.log(temp5_2==temp5_3)//true
</script>
6 实例:模块的 Singleton 模式 没有完全理解</br>
const FOO_KEY = Symbol.for('foo');</br>
function A() {</br>
this.foo = 'hello';</br>
}</br>
if (!global[FOO_KEY]) {</br>
global[FOO_KEY] = new A();</br>
}</br>
module.exports = global[FOO_KEY];</br>
<script>
</script>
</br> 7 内置的Symbol值 除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。 </br>
7.1 Symbol.hasInstance</br>
class MyClass{</br>
[Symbol.hasInstance](foo){</br>
return foo instanceof Array</br>
}</br>
}</br>
console.log("demo7:")</br>
console.log([1,2,3] instanceof new MyClass())//true</br>
<script>
class MyClass{
[Symbol.hasInstance](foo){
return foo instanceof Array
}
}
console.log("demo7:")
console.log([1,2,3] instanceof new MyClass())//true
</script>
7.2Symbol.isConcatSpreadable</br>
对象的Symbol.isConcatSpreadable属性等于一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开</br>
let obj = {length: 2, 0: 'c', 1: 'd'};</br>
['a', 'b'].concat(obj, 'e') // ['a', 'b', obj, 'e']</br>
obj[Symbol.isConcatSpreadable] = true;</br>
['a', 'b'].concat(obj, 'e') // ['a', 'b', 'c', 'd', 'e']</br></br></br>
</br> 7.3.Symbol.species</br>
有些类库是在基类的基础上修改的,那么子类使用继承的方法时,作者可能希望返回基类的实例,而不是子类的实例。</br>
class T1 extends Promise {</br>
}</br>
class T2 extends Promise {</br>
static get [Symbol.species]() {</br>
return Promise;</br>
}</br>
}</br>
console.log("demo9")</br>
console.log(new T1((r=>r())).then(v=>v) instanceof T1)//true</br>
console.log(new T2((r=>r())).then(v=>v) instanceof T2)//false</br></br>
<script>
class T1 extends Promise {
}
class T2 extends Promise {
static get [Symbol.species]() {
return Promise;
}
}
console.log("demo9")
console.log(new T1((r=>r())).then(v=>v) instanceof T1)//true
console.log(new T2((r=>r())).then(v=>v) instanceof T2)//false
</script>
7.4 Symbol.match</br>
let obj = {</br>
[Symbol.match](string) {</br>
return "heheda";</br>
}</br>
};;</br>
console.log("strstring".match(obj));//heheda</br>
<script>
let obj = {
[Symbol.match](string) {
debugger
return "heheda";
}
};;
console.log("strstring".match(obj));
//另外的调用方法
console.log("-----"+obj[Symbol.match]('strstring'))
</script>
7.5 Symbol.replace</br>
对象的Symbol.replace属性,指向一个方法,当该对象被String.prototype.replace方法调用时,会返回该方法的返回值。</br>
Symbol.replace方法会收到两个参数,第一个参数是replace方法正在作用的对象,上面例子是Hello,第二个参数是替换后的值,上面例子是World。</br>
const x = {</br>
[Symbol.replace](...s){</br>
console.log(s)</br>
}</br>
};</br>
'Hello'.replace(x, 'World') // ["Hello", "World"]</br>
<script>
const x = {
[Symbol.replace](...s){
console.log(s)
}
};
'Hello'.replace(x, 'World') // ["Hello", "World"]
</script>
7.6 剩余的可见es入门http://es6.ruanyifeng.com/</br>
Symbol.search</br>
对象的Symbol.search属性,指向一个方法,当该对象被String.prototype.search方法调用时,会返回该方法的返回值。</br>
Symbol.split 对象的Symbol.split属性,指向一个方法,当该对象被String.prototype.split方法调用时,会返回该方法的返回值</br>
Symbol.iterator</br>
Symbol.toPrimitive 对象的Symbol.toPrimitive属性,指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值</br>
Symbol.toStringTag 对象的Symbol.toStringTag属性,指向一个方法。在该对象上面调用Object.prototype.toString方法时,如果这个属性存在,它的返回值会出现在toString方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制[object Object]或[object Array]中object后面的那个字符串。</br>
Symbol.unscopables 对象的Symbol.unscopables属性,指向一个对象。该对象指定了使用with关键字时,哪些属性会被with环境排除。
Symbol.search demo </br>
String.prototype.search(regexp)</br>
// 等同于</br>
regexp[Symbol.search](this)</br>
class MySearch {</br>
constructor(value) {</br>
this.value = value;</br>
}</br>
[Symbol.search](string) {</br>
return string.indexOf(this.value);</br>
}</br>
}</br>
'foobar'.search(new MySearch('foo')) // 0</br>
Symbol.search demo</br>
class Collection {</br>
*[Symbol.iterator]() {</br>
let i = 0;</br>
while(this[i] !== undefined) {</br>
yield this[i];</br>
++i;</br>
}</br>
}</br>
}</br>
let myCollection = new Collection();</br>
myCollection[0] = 1;</br>
myCollection[1] = 2;</br>
for(let value of myCollection) {</br>
console.log(value);</br>
}</br>
</head>
<body>
<script>
</script>
</body>
</html>