之前看到过一道面试题,如何让a==1&& a==2 && a==3
等于true
,开始一看,一脸懵逼,后来搜索了下,看到了不同的解决方法.
访问修饰符
能够解决这个问题,毕竟每访问一次值加1就好啦.
var value = 0;
Object.defineProperty(window,'a',{
get:function(){
return this.value += 1;
}
})
console.log(a== 1 && a==2 && a==3);//true
不过,貌似对象还有一些方法能够改变访问到的值
;比如:
Object.prototype.valueOf()
Object.prototype.toString()
[Symbol.toPrimitive(hint)
Object.prototype.valueOf()
对象的`valueOf`旨在返回对象的原始值,会在需要将对象转换成原始值的地方`自动执行`.内置的一些对象已经定义`valueOf`方法,而对象默认则返回本身作为`valueOf()`的返回值。
Object.prototype.toString()
同理,`toString()`方法会返回表示该对象的字符串,会在对象预期要被转换成字符串的地方自动执行.对象默认的`toString()`方法会返回`[object type]`,这个`type`就是`对象构造函数的名称`
Symbol.toPrimitive
`[Symbol.toPrimitive](hint)`方法作用同`valueOf()`一样,但是优先级要高于`valueOf()`;而且该方法还会接受一个参数`hint`,这个参数用来表示期望转换的原始值的**具体类型**,有以下几种:
number
:数字类型string
:字符串类型default
默认
对象转换成原始值
很明显,以上三种方法都是在对象被预期转换成某种原始值时触发,那么触发的时机是什么,需要`何种类型`的原始值就要弄清楚了.
预期被转换成字符串类型
对应
hint
类型为string
- 进行输出的地方,如
alert()
. - String(obj):
let a = {
toString(){
return '2'
}
}
console.log(String(a));
3.字符串链接(+
)操作:
let a = {
toString(){
return '2'
}
}
console.log(a+'vv');
- 模板字符串:
let a = {
[Symbol.toPrimitive] (hint) {
console.log(hint) // string
return 2
}
}
console.log(`你是老${a}?`) // 你是老2?
预期被转换成数字类型
对应的
hint
类型为number
(1).除法:
let a = {
valueOf(){
return 2;
}
}
console.log(2/a,a/2);
可以使用[Symbol.toPrimitive]()
方法来验证一下:
let a = {
[Symbol.toPrimitive](hint){
console.log(hint);
return 2
}
}
console.log(2/a);
(2). Number(obj)
:
let a = {
[Symbol.toPrimitive](hint){
console.log(hint);
return 2
}
}
console.log(Number(a));
(3). 正负号
(注意不是加减运算)
let a = {
[Symbol.toPrimitive](hint){
console.log(hint);
return 2
}
}
console.log(+a);
console.log(-a);
预期被转换成默认类型(其他)
对应的
hint
类型为default
(1).数字加法 (即与对象相加的一方为数字类型)
let a = {
[Symbol.toPrimitive](hint){
console.log(hint);
return 2;
}
}
console.log(1+a); // 3
这一点有点意外,原以为像这种情况预期转换的类型应该是数字类型,但事实上却是default
;
(2).布尔运算:所有对象都被转换成true
:
let a = {
[Symbol.toPrimitive](hint){
console.log(hint); // 没有触发
return false;
}
}
console.log(Boolean(a),a && 123); // true 123
布尔运算包括==
;
三种方法触发的顺序
(1).首先,判断对象是否有`[Symbol.toPrimitive](hint)`方法,若有,则执行该方法:
let a = {
[Symbol.toPrimitive](hint){
console.log(hint);
return 'right your mother right';
},
toString(){
return 'f**k';
},
valueOf(){
return 'sb';
}
}
console.log(String(a));
(2).如果预期被转换成字符串类型
时,则优先执行toString()
方法:
let a = {
toString(){
return 'f**k'
},
valueOf() {
return 'sb'
}
}
console.log(String(a));
(3).如果预期被转换成默认类型或者数字类型时,则优先执行valueOf()
方法:
let a = {
toString(){
return 123
},
valueOf() {
return 456
}
}
console.log(Number(a));
注:若没有valueOf()
方法,但是定义了toString()
方法,则会执行toString()
方法;
let a = {
toString(){
return 123;
}
}
console.log(Number(a))