Step-By-Step icon indicating copy to clipboard operation
Step-By-Step copied to clipboard

如何让 (a == 1 && a == 2 && a == 3) 的值为true?

Open YvetteLau opened this issue 6 years ago • 60 comments

YvetteLau avatar May 23 '19 00:05 YvetteLau

var i = 1
Number.prototype.valueOf = function() {
    return i++
}
var a = new Number(1)
if (a == 1 && a == 2 && a == 3) {
    console.log('here')
}

toyxz avatar May 23 '19 01:05 toyxz

{[Symbol.toPrimitive]: ((i) => () => ++i) (0)}

shenanheng avatar May 23 '19 01:05 shenanheng

var aᅠ = 1; var a = 2; var ᅠa = 3; console.log(aᅠ==1 && a== 2 &&ᅠa==3)

dashengzi66 avatar May 23 '19 01:05 dashengzi66

var a = { value : 0 }; a.valueOf = function() { return this.value += 1; }; console.log(a==1 && a==2 && a==3);

jizx avatar May 23 '19 01:05 jizx

const a = { i: 1, toString: function () { return a.i++; } } if(a == 1 && a == 2 && a == 3) { console.log('Hello World!'); }

tpxiang avatar May 23 '19 01:05 tpxiang

var value = 0; Object.defineProperty(window,'a',{ get:function(){ return this.value += 1; } }) console.log(a== 1 && a==2 && a==3);//true

chang229 avatar May 23 '19 01:05 chang229

!(a == 1 && a == 2 && a == 3) 

Full-stop avatar May 23 '19 01:05 Full-stop

let a = { num:0, valueOf:function(){ return this.num += 1 } } let aa = (a == 1 && a == 2 && a == 3) console.log(aa)

Web3TomCat avatar May 23 '19 01:05 Web3TomCat

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/

taoyaoyaoa avatar May 23 '19 01:05 taoyaoyaoa

== 最大的特点在于允许进行类型转换,对于对象的转换会进行toPrimitive操作,也就是先调用valueOf方法如果不能返回基本类型的值就调用toString方法

var a = {
    valueOf: (function() {
        var temp = 1; // 使用闭包来保存这个变量
        return function() {
            return temp++;
        }
    }())
}

AILINGANGEL avatar May 23 '19 02:05 AILINGANGEL

var a = { i: 0, valueOf: function() { return this.i += 1; } } if(a==1 && a==2 && a==3){ console.log('nice, 马飞~~~') }

tianyuandsb avatar May 23 '19 02:05 tianyuandsb

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 ++ }

yelin1994 avatar May 23 '19 02:05 yelin1994

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()方法代替

wanglinyj avatar May 23 '19 02:05 wanglinyj

不太会,所以百度了下, 有几种方法实现 1、重写Object的toString或者valueOf 2、定义"a"属性,并重写它的getter方法 3、字符编码 4、数组toString隐含调用join()方法 参考了 https://majing.io/posts/10000006051204 https://www.codercto.com/a/41494.html

--感谢作者,感谢小姐姐

darlingyz avatar May 23 '19 02:05 darlingyz

== 运算符会进行隐式转换。

  • 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
  }

参考:

  1. 比较操作符
  2. Object​.prototype​.valueOf
  3. 从 (a==1&&a==2&&a==3) 成立中看javascript的隐式类型转换
  4. 第 38 题:下面代码中 a 在什么情况下会打印 1?

lqzo avatar May 23 '19 03:05 lqzo

var aᅠ = 1; var a = 2; var ᅠa = 3; console.log(aᅠ==1 && a== 2 &&ᅠa==3)

你这个也是一道经典的面试题 但是跟本题不是同一题呢~ 注意审题哦~

YvetteLau avatar May 23 '19 03:05 YvetteLau

`` 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()方法即可;

TTTTTTTZL avatar May 23 '19 03:05 TTTTTTTZL

let num=0; Object.definedProperty(this, 'a', { get(){ return ++num } }) console.log(a == 1 && a == 2 && a == 3) // true

kaiking01 avatar May 23 '19 03:05 kaiking01

  var i = 1
  var a = new Number(1)
  Number.prototype.valueOf =function() {
    return i++
  }
  console.log(a == 1 && a == 2 && a == 3);

zyq503454535 avatar May 23 '19 03:05 zyq503454535

对象形式

这种是通过 隐式转换时调用 toString 或者 valueOf 或者 Symbol.toPrimitive (es6)的形式来转换

  • toString
var a = {
    v:1,
    toString(){
        console.log('string');
        return this.v++
    },
}
if(a == 1 && a == 2 && a==3){
    console.log('成功')
}
  • valueOf
var a = {
    v:1,
    valueOf(){
        console.log('string');
        return this.v++
    },
}
if(a == 1 && a == 2 && a==3){
    console.log('成功')
}
  • Symbol.toPrimitive
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.toPrimitivetoString 或者 valueOf 同时存在时 会优先调用 Symbol.toPrimitive 如果 Symbol.toPrimitive 不存在时 会先调用 valueOf,如果valueOf的返回值还是一个对象时(默认情况 会返回对象本身)则再调用 toString,如果toString 返回值还是一个对象(人为定义覆盖,默认会返回[object Object]) 则抛出错误

getter 拦截

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方法

333

函数形式


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 其他的方法 都是隐式调用了 toStringvalueOfSymbol.toPrimitive 来完成转换

wubetter avatar May 23 '19 04:05 wubetter

== 会将左右两边的值转化成相同的原始类型,然后再去比较他们是否相等。

  1. 如果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 );

  2. 如果a是一个数组Array,在数组转换成字符串的时候,数组toString会隐含调用join()方法 const a = [1, 2, 3]; a.join = a.shift; console.log( a == 1 && a == 2 && a ==3 );

Diamondjcx avatar May 23 '19 06:05 Diamondjcx

!( a == 1 && a == 2 && a ==3 ) 偷个懒~o( ̄︶ ̄)o

补充一种(今天刚刚get到的): var a console.log( (a == 1 && a == 2 && a ==3) || ture ) 持续偷懒(^o^)/~

zxh008 avatar May 23 '19 07:05 zxh008

var a=1; var a=2; var a = 3; console.log(a==1 && a==2 &&a==3);

chongyangwang avatar May 23 '19 08:05 chongyangwang

var num= 1 Object.defineProperty("window", "a", { get(){ return num++ } })

13775906336 avatar May 23 '19 08:05 13775906336

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要等于三个不同的数,所以自身改写函数返回不同值即可得到结果

Talljack avatar May 23 '19 08:05 Talljack

const a = { value: 0 }

a.valueOf = function () { return this.value += 1 } console.log(a==1 && a==2 && a==3)

== 在js 中 会发生类型转换 ===全等择不会发生强转

== 会把左右两边的值 转化为相同的原始数据类型然后在去比较他们是否相当 如果输入的是个基本类型就直接返回这个类型值 如果输入是Object类型 那就先调用输入对象的valueOf()如果是基本类型的话就直接返回 如果不是在调用toSting() 是基本类型 就返回他 js 在解析a==1 时 1 是基本数据类型 所以会把a 转换为Nubmer a.valueof 覆盖的原来的valueof 被调用时 会返回1 自增+1返回自身

=== 全等下不会执行 valueof 此时就可以 用到Object.defineProperty 因为get 和 set是可以通过"."操作符调用的方法

var v = 1;

Object.defineProperty(window,'a',{ get(){ return v++; } }) a == 1 && a == 2 && a==3

zhangxianhui avatar May 23 '19 09:05 zhangxianhui

let a = {
  i: 1,
  valueOf: function() {
    return a.i++;
  }
}

// == 的时候会隐形调用了 valueOf() 或者 toString() 
console.log(a == 1 && a == 2 && a == 3); // true

ccvaille avatar May 23 '19 10:05 ccvaille

const a = {
   num: 0,
   valueOf: function() {
         return this.num += 1
   }
};
console.log(a==1 && a==2 && a==3); // true

  1. 使用相等操作符,js会做强制类型转化
  2. 我们的对象每次调用valueOf()它的值会增加1
  3. (a==1 && a==2 && a==3) 当他们比较时,JavaScript会企图将对象转化成数字的类型,进行比较。
  4. 当要转化的是一个Object的时候,JavaScript会调用本身的valueOf()方法,这个时候就可以实现 this.num += 1

zhmfe avatar May 23 '19 10:05 zhmfe

===== 的区别

  • === 不需要进行类型转换, 只有类型相同并且值相等时, 才返回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);

yuzhang9804 avatar May 23 '19 11:05 yuzhang9804

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,以此类推。

zihuasunshine avatar May 23 '19 12:05 zihuasunshine