# 前端爱好者学习周刊:第10期
20200412
# 1.new Proxy()
使用Proxy对象可以给一个对象添加自定义行为:
const handler = {
set: () => console.log('Added a new property!'),
get: () => console.log('Accessed a property!')
}
const person = new Proxy({}, handler)
person.name = 'lydia' // Added a new property
person.name // Accessed a property
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
const p = new Proxy(target, handler)
1
# isNaN
和Number.isNaN
参考:
# 1).NaN
NaN
即(Not-A-Number
不是一个数字);
获取:
Number.NaN
js中唯一一个与自身不相等的存在:
NaN == NaN// false
NaN!==NaN
的原因:NaN
只是Number
上的一个静态属性;如Number('echo')
会得到NaN
,它只是为了说明这个值不是一个数字,一种表示方法,而非一个精准有效的值,因此NaN
不能参与计算,也无法与自身比较。产生
NaN
的情况:
Number('echo') //NaN
parseInt('echo123') //NaN
parseInt('123echo') //123
parseFloat('时间跳跃123.1') //NaN
parseFloat('123.1时间跳跃') //123.1
1 - '听风是风' //NaN
1 * '123时间跳跃' //NaN
1 / 'echo123' //NaN
0 / 0 //NaN
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 2).isNaN()
isNaN
是window
上的方法
当我们向isNaN传递一个参数,它的本意是通过Number()方法尝试转换参数的类型为Number,如果转换成功返回false,否则转返回true,它只是判断这个参数能否转成数字而已,并不是判断是否严格等于NaN。不能转成数字即NaN
console.log(isNaN(null)); //false
console.log(isNaN(true)); //false
console.log(isNaN(false)); //false
console.log(isNaN(0)); //false
console.log(isNaN(undefined)); //true
console.log(isNaN("AB")); //true
console.log(isNaN({ a: 1 })); //true
console.log(isNaN(NaN)); //true
console.log(isNaN(123)) //false
console.log(isNaN('123时间跳跃')) //true
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
console.log(Number(null)); //0
console.log(Number(true)); //1
console.log(Number(false)); //0
console.log(Number(0)); //0
console.log(Number(undefined)); //NaN
console.log(Number("AB")); //NaN
console.log(Number({ a: 1 })); //NaN
console.log(Number(NaN)); //NaN
console.log(Number(123)) //123
console.log(Number('123时间跳跃')) //NaN
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 3).Number.isNaN()
ES6中提供了一个Number.isNaN()
方法用于判断一个值是否严格等于NaN
console.log(Number.isNaN(null)); //false
console.log(Number.isNaN(true)); //false
console.log(Number.isNaN(false)); //false
console.log(Number.isNaN(0)); //false
console.log(Number.isNaN(undefined)); //false
console.log(Number.isNaN("AB")); //false
console.log(Number.isNaN({ a: 1 })); //false
console.log(Number.isNaN(NaN)); //true
console.log(Number.isNaN(123)) //false
console.log(Number.isNaN('123时间跳跃')) //false
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Number.isNaN()
的 polyfill
:
if (!Number.isNaN) {
Number.isNaN = function(n) {
return typeof n === "number" && window.isNaN( n );
};
}
1
2
3
4
5
2
3
4
5
// 简单的实现,利用只有 NaN 不跟自己相等的特性
if (!Number.isNaN) {
Number.isNaN = function(n) {
return return value !== value;
};
}
1
2
3
4
5
6
2
3
4
5
6
# 3.for in和for of
for in
可以遍历一个对象自有的、继承的、可枚举的、非Symbol的属性for of
可以迭代可迭代对象(包括array
,Map
,Set
,String
,arguments
等
# 4.error
- 当js找不到要访问的值的引用时,抛出
ReferenceErrors
- 当值不是预期类型的时,会抛出
TypeError
- 当你编写了一个非有效的JS时,比如
return
写成了retunr
时,会抛出语法错误SyntaxError
# 5. 从a == 1 && a == 2 && a == 3
看隐式转换
【原题】-下面代码中 a 在什么情况下会打印 1 (opens new window)
出发点一:取a
值时会进行get
# 1).修改getter
# (1).通过Object.defineProperty
来对window
对象上的a
属性重新定义getter
Object.defineProperty(window, 'a', {
get: function() {
return this.value = this.value ? (this.value += 1) : 1;
}
})
1
2
3
4
5
2
3
4
5
# (2).new Proxy()可以给一个对象添加自定义行为
var a1 = new Proxy({}, {
i: 1,
get() {
return () => this.i++
}
}
)
1
2
3
4
5
6
7
2
3
4
5
6
7
出发点二:a == 1
做这个运算的时候会执行隐式转换,就会调用toString()
,valueOf()
,[Symbol.toPrimitive]
# 2).隐式转换toString(),valueOf(),[Symbol.toPrimitive]
var a = {
i: 1,
valueOf() {
return a.i++;
},
toString() {
return a.i++;
},
[Symbol.toPrimitive]() { // 优先级最高
return a.i++;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
// ES6的生成器
const a3 = {
gn: (function* () {
yield 1;
yield 2;
yield 3;
})(),
valueOf() {
return this.gn.next().value;
}
};
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# Symbol.toPrimitive
参考:toString方法和valueOf方法以及Symbol.toPrimitive方法的学习 (opens new window)
对象的Symbol.toPrimitive属性。指向一个方法。该对象被转化为原始类型的值时,会调用这个办法,返回该对象对应的原始类型值。 Symbol.toPrimitive被调用时,会接受一个字符串参数,表示当前运算的模式,一个有三种模式。
- Number:该场合需要转成数值
- String:该场合需要转成字符串
- Default:该场合可以转成数值,也可以转成字符串。
// 没有 Symbol.toPrimitive 属性的对象
var obj1 = {};
console.log(+obj1); //NaN
console.log(`${obj1}`); //"[object Object]"
console.log(obj1 + ""); //"[object Object]"
1
2
3
4
5
2
3
4
5
// 拥有 Symbol.toPrimitive 属性的对象
let obj = {
[Symbol.toPrimitive](hint) {
if(hint === 'number'){
console.log('Number场景');
return 123;
}
if(hint === 'string'){
console.log('String场景');
return 'str';
}
// if(hint === 'default'){
console.log('Default 场景');
return 'default';
// }
}
}
console.log(2*obj); // Number场景 246
console.log(3+obj); // String场景 3default
console.log(obj + ""); // Default场景 default
console.log(String(obj)); //String场景 str
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21