Open YvetteLau opened 5 years ago
{[Symbol.toPrimitive]: ((i) => () => ++i) (0)}
var aᅠ = 1; var a = 2; var ᅠa = 3; console.log(aᅠ==1 && a== 2 &&ᅠa==3)
var a = { value : 0 }; a.valueOf = function() { return this.value += 1; }; console.log(a==1 && a==2 && a==3);
const a = { i: 1, toString: function () { return a.i++; } } if(a == 1 && a == 2 && a == 3) { console.log('Hello World!'); }
var value = 0; Object.defineProperty(window,'a',{ get:function(){ return this.value += 1; } }) console.log(a== 1 && a==2 && a==3);//true
!(a == 1 && a == 2 && a == 3)
let a = { num:0, valueOf:function(){ return this.num += 1 } } let aa = (a == 1 && a == 2 && a == 3) console.log(aa)
1.const a = { i: 1, toString: function () { return a.i++; } } if(a == 1 && a == 2 && a == 3) { console.log('Hello World!'); } 2.var aᅠ = 1; var a = 2; var ᅠa = 3; if(aᅠ==1 && a== 2 &&ᅠa==3) { console.log("Why hello there!") } 3.var val = 0; Object.defineProperty(window, 'a', { get: function() { return ++val; } }); if (a == 1 && a == 2 && a == 3) { console.log('yay'); } 参考了http://web.jobbole.com/93874/
== 最大的特点在于允许进行类型转换,对于对象的转换会进行toPrimitive操作,也就是先调用valueOf方法如果不能返回基本类型的值就调用toString方法
var a = {
valueOf: (function() {
var temp = 1; // 使用闭包来保存这个变量
return function() {
return temp++;
}
}())
}
var a = { i: 0, valueOf: function() { return this.i += 1; } } if(a==1 && a==2 && a==3){ console.log('nice, 马飞~~~') }
var a = [1, 2, 3] a.join = a.shift console.log(a==1 && a==2 && a==3) 利用数组转化为字符串都会调用,Array.join
或者 var a = { value: 1, toString: function () { return this.value ++ }
let a = { value: 0, valueOf: function() { return this.value += 1; } } console.log(aᅠ==1 && a== 2 &&ᅠa==3) JS对象有toString() 和valueOf()两个方法,toString()将该对象的原始值以字符串的形式返回,valueOf()返回最适合该对象的原始值,这两个方法一般是交由JS去隐式调用,以满足不同的运算情况。 在数值运算里,会优先调用valueOf(),在字符串运算里,会优先调用toString()。 1.用运算符对对象进行转换的时候valueOf()的优先级高于toString() 2.对对象进行强字符串转换时会优先调用toString() 3.toString()方法不能对null和undefined进行字符串转换,可以用String()方法代替
不太会,所以百度了下, 有几种方法实现 1、重写Object的toString或者valueOf 2、定义"a"属性,并重写它的getter方法 3、字符编码 4、数组toString隐含调用join()方法 参考了 https://majing.io/posts/10000006051204 https://www.codercto.com/a/41494.html
--感谢作者,感谢小姐姐
== 运算符会进行隐式转换。
Object ==操作符会尝试通过方法valueOf和toString将对象转换为其原始值(一个字符串或数字类型的值)。
const a = {
i: 1,
// valueOf 也可达到相同效果
toString: function () {
return a.i++;
}
}
a == 1 && a == 2 && a == 3; // true
Array 对于数组对象,toString 方法返回一个字符串,该字符串由数组中的每个元素的 toString() 返回值经调用 join() 方法连接(由逗号隔开)组成。
var a = [1,2,3];
a.join = a.shift;
a == 1 && a == 2 && a == 3; // true
Symbol Symbol对象被转为原始类型的值时,会调用 toPrimitive 方法,返回该对象对应的原始类型值。
let a = {
[Symbol.toPrimitive]: ((i) => () => ++i) (0)
};
a == 1 && a == 2 && a == 3; // true
修改window的get方法
var val = 0;
Object.defineProperty(window, 'a', {
get: function() {
return ++val;
}
});
a == 1 && a == 2 && a == 3; // ture
利用with关键字 emmm... with关键字好像很少用到
var i = 0;
with({
get a() {
return ++i;
}
}) {
a == 1 && a == 2 && a == 3; // true
}
参考:
var aᅠ = 1; var a = 2; var ᅠa = 3; console.log(aᅠ==1 && a== 2 &&ᅠa==3)
你这个也是一道经典的面试题 但是跟本题不是同一题呢~ 注意审题哦~
`` var a = new Number();
var i = 1;
a.valueOf = function(){
return i++; }
console.log(a == 1 && a == 2 && a == 3) ---> true
`` 复杂数据类型与原始数据比较时,会隐式调用toString()和valueOf(),将对象转换成原始值; 所以object用来比较时,改写toString()和valueOf()方法即可;
let num=0; Object.definedProperty(this, 'a', { get(){ return ++num } }) console.log(a == 1 && a == 2 && a == 3) // true
var i = 1
var a = new Number(1)
Number.prototype.valueOf =function() {
return i++
}
console.log(a == 1 && a == 2 && a == 3);
这种是通过 隐式转换时调用 toString
或者 valueOf
或者 Symbol.toPrimitive
(es6)的形式来转换
var a = {
v:1,
toString(){
console.log('string');
return this.v++
},
}
if(a == 1 && a == 2 && a==3){
console.log('成功')
}
var a = {
v:1,
valueOf(){
console.log('string');
return this.v++
},
}
if(a == 1 && a == 2 && a==3){
console.log('成功')
}
var a = {
v:1,
//该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值
//被调用时,会接受一个字符串参数,表示当前运算的模式,一共有三种模式(number,string,default)
[Symbol.toPrimitive](h){
console.log(h);
return this.v++
}
}
if(a == 1 && a == 2 && a==3){
console.log('成功')
}
注意:对象隐式转换成基本类型时,如果 Symbol.toPrimitive
和 toString
或者 valueOf
同时存在时 会优先调用 Symbol.toPrimitive
如果 Symbol.toPrimitive
不存在时 会先调用 valueOf
,如果valueOf
的返回值还是一个对象时(默认情况 会返回对象本身)则再调用
toString
,如果toString
返回值还是一个对象(人为定义覆盖,默认会返回[object Object]) 则抛出错误
var v = 1;
Object.defineProperty(window,'a',{
get(){
return v++;
}
})
if(a == 1 && a == 2 && a==3){
console.log('成功')
}
var a = [1,2,3];
//方法1
a[Symbol.toPrimitive] = function(){return this.shift()};
//方法2
// arr.valueOf = function(){return this.shift()}
//方法3
//a.toString = function(){return this.shift()}
//方法4
a.join = a.shift;
if(a == 1 && a == 2 && a==3){
console.log('成功')
}
对于方法4理解:a隐式转换会调用toString方法 而toString方法内部会调用 join方法
var a = (()=>{
let n=0;
let s = ()=>1;
s.toString = ()=>++n; //这里还可以用valueOf ,Symbol.toPrimitive
return s;
})();
if(a == 1 && a == 2 && a==3){
console.log('成功')
}
这里除了 getter
其他的方法 都是隐式调用了 toString
或 valueOf
或 Symbol.toPrimitive
来完成转换
== 会将左右两边的值转化成相同的原始类型,然后再去比较他们是否相等。
如果a是一个对象Object,在执行a==的时候首先会执行valueOf方法,如果没有valueOf方法,会执行toString方法。 const a = { value: 0 } a.valueOf = function () { return this.value += 1 } console.log( a == 1 && a == 2 && a == 3 );
如果a是一个数组Array,在数组转换成字符串的时候,数组toString会隐含调用join()方法 const a = [1, 2, 3]; a.join = a.shift; console.log( a == 1 && a == 2 && a ==3 );
!( a == 1 && a == 2 && a ==3 )
偷个懒~o( ̄︶ ̄)o
补充一种(今天刚刚get到的): var a console.log( (a == 1 && a == 2 && a ==3) || ture ) 持续偷懒(^o^)/~
var a=1; var a=2; var a = 3; console.log(a==1 && a==2 &&a==3);
var num= 1 Object.defineProperty("window", "a", { get(){ return num++ } })
var a = { val: 0, valueOf: function() { return this.val += 1; } } if (a == 1 && a == 2 && a == 3) {console.log('xiaoxiao');} // == 号会发生隐士类型转换,如果发现所比较的数类型不同的话就会进行转换 如果两个数一个为undefined另一个为null则直接返回true 如果一个为数字另一个为string则将string转换为Number 如果一个为Boolean另一个为Number则将Boolean转换为Number 如果一个为对象另一个为Number则将object转换为原始类型 1、首先会调用自身的valueOf,当然也会去查找原型上有没有,如果有则直接转 2、其次才会调用自身的toString方法,当然也会去原型链上查找是否存在,然后进行相应的转换 3、如果上面两个方法都没有找到那么就返回false 本题则是在考==号的隐士转换,其次是因为a要等于三个不同的数,所以自身改写函数返回不同值即可得到结果
a.valueOf = function () { return this.value += 1 } console.log(a==1 && a==2 && a==3)
== 会把左右两边的值 转化为相同的原始数据类型然后在去比较他们是否相当 如果输入的是个基本类型就直接返回这个类型值 如果输入是Object类型 那就先调用输入对象的valueOf()如果是基本类型的话就直接返回 如果不是在调用toSting() 是基本类型 就返回他 js 在解析a==1 时 1 是基本数据类型 所以会把a 转换为Nubmer a.valueof 覆盖的原来的valueof 被调用时 会返回1 自增+1返回自身
Object.defineProperty(window,'a',{ get(){ return v++; } }) a == 1 && a == 2 && a==3
let a = {
i: 1,
valueOf: function() {
return a.i++;
}
}
// == 的时候会隐形调用了 valueOf() 或者 toString()
console.log(a == 1 && a == 2 && a == 3); // true
const a = {
num: 0,
valueOf: function() {
return this.num += 1
}
};
console.log(a==1 && a==2 && a==3); // true
==
和 ===
的区别
===
不需要进行类型转换, 只有类型相同并且值相等时, 才返回true==
如果两者类型不同, 则会进行隐式转换如果对象和简单数据类型比较, 会先调用valueOf
方法, 如果返回还是对象则在调用toString
方法, 这时我们就可以通过 attribute 拦截实现目的
const a = {
// valueOf 也是一样
toString: (i => _ => i++ )(1)
}
console.log(a == 1 && a == 2 && a == 3);
数组调用 toString 方法, 会调用本身的join 方法
const a = [1,2,3];
// 利用shift 每次从头部截取一个值来实现
a.join = a.shift;
console.log(a == 1 && a == 2 && a == 3)
ES6
新增Symbol
, 对象的Symbol.toPrimitive
属性,指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。
const a = {
[Symbol.toPrimitive]: (i => _ => i++ )(1)
}
console.log(a == 1 && a == 2 && a == 3)
如果要实现 (a === 1 && a === 2 && a === 3)
为true, 这可以通过拦截getter
const num = new Proxy({}, {
get: (i => _ => i++ )(1)
})
console.log(num.a === 1 && num.a === 2 && num.a === 3);
1.运算子是对象时候的valueOf toString 方法
const a = {
i: 0,
valueOf: function(){
return a.i++;
}
}
console.log(a==1 && a==2 && a==3); // true
如果原始类型的值与对象比较,对象会先转换成原始类型的值,转换规则,对象先调用valueOf方法,若还是对象,再调用toString方法。
2.利用数组特性
const a = [1,2,3];
a.join = a.shift;
console.log(a==1 && a==2 && a==3); // true
数组也是对象,与原始类型的值作比较,也会调用toString方法,返回一个字符串,该字符串由数组中的每个元素调用toString()再调用自身的join()方法生成。这种方法,将数组的join方法改写为shift方法。当a==1时,a调用toString()得到‘1’,再调用join即shift方法,返回1,并且删掉第一个元素,可以得到‘1’==1,以此类推。
let a = { toString: (function(){ let a = 1 return function(){ return a ++ } } )() }
==
操作符在左右数据类型不一致时,会先进行隐式转换。
a == 1 && a == 2 && a == 3
的值意味着其不可能是基本数据类型。因为如果 a 是 null 或者是 undefined bool类型,都不可能返回true。
因此可以推测 a 是复杂数据类型,JS 中复杂数据类型只有 object
,回忆一下,Object 转换为原始类型会调用什么方法?
[Symbol.toPrimitive]
接口,那么调用此接口,若返回的不是基本数据类型,抛出错误。[Symbol.toPrimitive]
接口,那么调用 valueOf
接口,若返回的不是基本数据类型,那么调用 toString
接口,若返回的还不是基本数据类型,那么抛出异常。如以下代码,我们可以清楚的看出优先调用的是 [Symbol.toPrimitive]
接口,其它规则大家可以自行编写代码进行验证。
let obj = {
[Symbol.toPrimitive]() {
return 100;
},
valueOf() {
return 200;
},
}
console.log(obj == 100);//true
那么对于这道题,只要 [Symbol.toPrimitive]
接口,第一次返回的值是 1,然后递增,即成功成立。
let a = {
[Symbol.toPrimitive]: (function() {
let i = 1;
//闭包的特性之一:i 不会被回收
return function() {
return i++;
}
})()
}
console.log(a == 1 && a == 2 && a == 3); //true
前面我们说了在没有部署 [Symbol.toPrimitive]
接口的情况下,隐式转换会调用 valueOf
接口,那么以下代码也是等价的:
let a = {
valueOf: (function() {
let i = 1;
//闭包的特性之一:i 不会被回收
return function() {
return i++;
}
})()
}
console.log(a == 1 && a == 2 && a == 3); //true
另外一种调用 toString
接口的情况,相信无需我再说明。
重写 a
属性的 getter
方法
使用 Object.defineProperty
定义的属性,在获取属性时,会调用 get
方法。利用这个特性,我们在 window
对象上定义 a
属性,如下:
let i = 1;
Object.defineProperty(window, 'a', {
get: function() {
return i++;
}
});
console.log(a == 1 && a == 2 && a == 3); //true
ES6 新增了 Proxy
,在 Vue 中也得到了应用,大家可以思考一下,此处是否使用 Proxy
实现。
join
方法。数组的 toString
接口默认调用数组的 join
方法,
let a = [1, 2, 3];
a.join = a.shift;
console.log(a == 1 && a == 2 && a == 3); //true
对于这道题的理解和考察的知识点如下; 1.对二元运算的考察, (1)‘==’和‘===’的理解,前者是隐式转化的比较,后者是类型和值得二者都相等的比较。 2.对隐式类型转化的考察, 对于对象的转化自身携带的两个原声的方法 toString()和valueOf() let a={ a:1, toSting(){ return a+=1; }
} if(a==1&&a==2&&a==3){ console.log("加油") } 注意:a被隐式的转化成了数字,或者转化成了字符串或者原对象,进行比较
const a = [1, 2, 3]; a.join = a.shift; console.log( a == 1 && a == 2 && a ==3 );
var a = { n:1, toString(){ return this.n++ }, valueOf(){ return this.n++ } } if(a == 1 && a == 2 && a == 3){ console.log('重写隐式调用') }
法一: const a = { i: 1, toString: function () { return a.i++; } }
if(a == 1 && a == 2 && a == 3) { console.log('Hello World!'); }
对象a和原始类型比较,对象会转为原始类型,再进行比较。 对象转换成原始类型的值,算法先调用valueOf()方法; 如果返回的还是对象,再接着调用toString方法 所以每次比较一次,都会返回数字,在自增。
法二: 利用数组的特性 var a=[1,2,3]; a.join=a.shift; console.log(a==1&&a==2&&a==3); Array对象的toString方法,会返回一个字符串,该字符串由数组的每个元素的toString返回值经调用 join()方法连接组成。 这里把join方法改为shift方法,每次返回第一个元素,原数组删除第一个值
法三: var i=0; with({ get a(){ return ++i; } }){ if (a==1&&a==2&&a==3) console.log('Hello'); }
法四:修改了window的get方法 var val=0; Object.defineProperty(window,'a',{ get: function(){ return ++val; }}); if(a==1&&a==2&&a==3){ console.log('Hello'); }
法四: ES6的symbol特性,闭包返回函数 let a={[Symbol.toPrimitive]:((i)=>()=>++i)(0)} console.log(a==1&&a==2&&a==3);//true
const a = {
i:1,
toString: function() {
return a.i++;
}
}
console.log(a==1 && a==2 &&a==3); // true
JavaScript的数据类型包括两种,基础数据类型(原始值)和复杂数据类型(对象值)
==两个等号时,当==左右两边数据类型不一致时,会发生隐式转换,所以基础数据类型肯定无法实现 console.log(a==1 && a==2 &&a==3); // true,考虑利用复杂数据类型 object 上述代码中一是利用隐式原则,二是利用闭包的变量不会回收的机制,使得a的值能继续累加
引用了这篇文章 说实话,没看懂~看来要仔细研究一下了
对象类型转换
var a = { i:1, toString:function(){ return a.i++; } }
数组类型转换
var a = [1,2,3]; a.join = a.shift; console.log(a == 1 && a == 2 && a == 3);
定义a的get
var val = 0; Object.defineProperty(window, 'a', { get: function() { return ++val; } }); console.log(a == 1 && a == 2 && a == 3);
Proxy 形式实现:
const a = new Proxy({}, {
v: 1,
get: function () {
return () => this.v++;
}
});
console.log(a == 1 && a == 2 && a == 3); // true
这种题目好像没碰到过,这下长见识了 toString()/ValueOf() 他们的作用是获取数字的基本类型
const a = { value: 0 }
a.toString = function(){
return this.value++
}
console.log(a==1&&a==2&&a==3)
我看了小伙伴其他的方法还是不理解
这种题目好像没碰到过,这下长见识了 toString()/ValueOf() 他们的作用是获取数字的基本类型
const a = { value: 0 } a.toString = function(){ return this.value++ } console.log(a==1&&a==2&&a==3)
我看了小伙伴其他的方法还是不理解
可以看看我的那条答案,写得比较详细了~
Proxy 形式实现:
const a = new Proxy({}, { v: 1, get: function () { return () => this.v++; } }); console.log(a == 1 && a == 2 && a == 3); // true
手动点赞~
首先,在JS中,宽松匹配 ==会先将左右两边的值转化成相同的原始类型,然后再去比较他们是否相等。 即:相等和不相等——先转换再比较 (==) 全等和不全等——仅比较而不转换 (===) 基本转换规则: ①、如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false转换为0,而true转换为1; ②、如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值 ③、如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较 注意:!(取反)的时候可将变量转换成boolean类型,null、undefined、NaN以及空字符串('')取反都为true,其余都为false 回到本题: a == 1 && a == 2 && a == 3 值为true 即 a 是个复杂数据类型:object。 // 如果是个对象
var a = { value: 0 }
a.valueOf = function () {
return this.value += 1
}
if (a == 1 && a == 2 && a == 3) {
console.log("艳姐,你好!")
}
// 如果是个数组
var b = [1, 2, 3];
b.join = b.shift;
if (b == 1 && b == 2 && b == 3) {
console.log("艳姐,我知道你不用百雀羚!")
}
// 通过proxy 进行拦截操作
var c = new Proxy({ i: 0 }, {
get(target) {
return () => target.i+=1;
}
})
if (c == 1 && c == 2 && c == 3) {
console.log("艳姐,今天又让我长知识了")
}
// 方法四 也适合严格相等 ===
// 重新定义 window 对象中的d 属性
var value = 0; //window.value
Object.defineProperty(window, "d", {
get: function () {
return this.value += 1
}
})
if (d == 1 && d == 2 && d == 3) {
console.log("艳姐,每天进步一点点,做不一样的自己!")
}
当对象进行类型转换时,先执行valueOf() 函数,如果没有则执行toString()函数进行类型转换。
var arr =[2,3,"f"];
arr.valueOf = function(){
console.log("valueOf")
}
arr.toString = function(){
console.log("toString")
}
console.log(arr==2)
艳姐,不知道这次是否能明白 可以试着把 valueOf 函数注释掉,在执行看一下效果
想用proxy结果实验了好久没成功,只能换个方式了 var c = 0 window.defineGetter('a',function(){return ++c})//__竟然不能显示 a == 1 && a == 2 && a == 3
想用proxy结果实验了好久没成功,只能换个方式了 var c = 0 window.defineGetter('a',function(){return ++c})//__竟然不能显示 a == 1 && a == 2 && a == 3
可以写在代码块中,不然会默认变成加粗。
!(a == 1 && a == 2 && a == 3) 取反 (微信名:RUN)
let a = { value: 0, valueOf: function() { return this.value += 1; } }
首先,在JS中,宽松匹配 ==会先将左右两边的值转化成相同的原始类型,然后再去比较他们是否相等。 即:相等和不相等——先转换再比较 (==) 全等和不全等——仅比较而不转换 (===) 基本转换规则: ①、如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false转换为0,而true转换为1; ②、如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值 ③、如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较 注意:!(取反)的时候可将变量转换成boolean类型,null、undefined、NaN以及空字符串('')取反都为true,其余都为false 回到本题: a == 1 && a == 2 && a == 3 值为true 即 a 是个复杂数据类型:object。 // 如果是个对象
var a = { value: 0 } a.valueOf = function () { return this.value += 1 } if (a == 1 && a == 2 && a == 3) { console.log("艳姐,你好!") }
// 如果是个数组
var b = [1, 2, 3]; b.join = b.shift; if (b == 1 && b == 2 && b == 3) { console.log("艳姐,我知道你不用百雀羚!") }
// 通过proxy 进行拦截操作
var c = new Proxy({ i: 0 }, { get(target) { return () => target.i+=1; } }) if (c == 1 && c == 2 && c == 3) { console.log("艳姐,今天又让我长知识了") }
// 方法四 也适合严格相等 === // 重新定义 window 对象中的d 属性
var value = 0; //window.value Object.defineProperty(window, "d", { get: function () { return this.value += 1 } }) if (d == 1 && d == 2 && d == 3) { console.log("艳姐,每天进步一点点,做不一样的自己!") }
O(∩_∩)O哈哈~一起每天进步一点点~
!(a == 1 && a == 2 && a == 3) 取反 (微信名:RUN)
偷懒啦~~~被我发现了~