Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 38 题:下面代码中 a 在什么情况下会打印 1? #57

Open
zpzxgcr opened this issue Mar 21, 2019 · 65 comments
Open

第 38 题:下面代码中 a 在什么情况下会打印 1? #57

zpzxgcr opened this issue Mar 21, 2019 · 65 comments

Comments

@zpzxgcr
Copy link

zpzxgcr commented Mar 21, 2019

题目如下

var a = ?;
if(a == 1 && a == 2 && a == 3){
 	conso.log(1);
}

答案解析 因为==会进行隐式类型转换 所以我们重写toString方法就可以了

var a = {
  i: 1,
  toString() {
    return a.i++;
  }
}

if( a == 1 && a == 2 && a == 3 ) {
  console.log(1);
}
@Yanhua67
Copy link

Yanhua67 commented Mar 21, 2019

let a = [1,2,3];
a.toString = a.shift;
if( a == 1 && a == 2 && a == 3 ) {
  console.log(1);
}

@jefferyE
Copy link

这题考察的应该是类型的隐式转换,考引用类型在比较运算符时候,隐式转换会调用本类型toString或valueOf方法.
解答:

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

@Moriarty02
Copy link

这个题目考察==的隐式转换吧

利用toString

let a = {
  i: 1,
  toString () {
    return a.i++
  }
}

if(a == 1 && a == 2 && a == 3) {
  console.log('1');
}

利用valueOf

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

if(a == 1 && a == 2 && a == 3) {
  console.log('1');
}

数组这个就有点妖了

var a = [1,2,3];
a.join = a.shift;
if(a == 1 && a == 2 && a == 3) {
  console.log('1');
}

ES6的symbol

let a = {[Symbol.toPrimitive]: ((i) => () => ++i) (0)};
if(a == 1 && a == 2 && a == 3) {
  console.log('1');
}

从 (a==1&&a==2&&a==3) 成立中看javascript的隐式类型转换

@win7killer
Copy link

win7killer commented Mar 21, 2019

let a = {
    gn: (function* () {
        yield 1;
        yield 2;
        yield 3;
    })(),
    valueOf() {
        return this.gn.next().value;
    }
};

@win7killer
Copy link

win7killer commented Mar 21, 2019

Object.defineProperty(window, 'a', {
    get: function() {
        return this.value += 1;
    }
});

要改下,不然报错。你这个挺好,可以做 ===

Object.defineProperty(window, 'a', {
    get: function() {
	if (this.value) {
	    return this.value += 1
	} else {
	    return this.value = 1;
	}
    }
});

@jjeejj
Copy link
Contributor

jjeejj commented Mar 21, 2019

Object.defineProperty(window, 'a', {
    get: function() {
        return this.value += 1;
    }
});

要改下,不然报错。你这个挺好,可以做 ===

Object.defineProperty(window, 'a', {
    get: function() {
	if (this.value) {
	    return this.value += 1
	} else {
	    return this.value = 1;
	}
    }
});

精简一下代码:

Object.defineProperty(window, 'a', {
    get: function() {
          return this.value = this.value ? (this.value += 1) : 1;
    }
});

@HankXu
Copy link

HankXu commented Mar 21, 2019

一开始没转过来,群里老哥提了一声才想到这个方向

var a = Object.create({
    count: 0,
    valueOf: function() {
        return ++this.count;
    }
});

if (a == 1 && a == 2 && a == 3) {
    console.log(1);
}

@XinJack
Copy link

XinJack commented Mar 21, 2019

第一反应想到的是a = console.log(1)😂😂

@jiyuzhuang
Copy link

@XinJack 感觉你这个才是最优解啊,半天说不出一句话。

@RicoLiu
Copy link

RicoLiu commented Mar 27, 2019

@XinJack console.log() 的返回值是 undefined

@leehomeok
Copy link

数组这个 a.join = a.shift; 没看懂啊

@jjeejj
Copy link
Contributor

jjeejj commented Mar 28, 2019

数组这个 a.join = a.shift; 没看懂啊

把 shift 方法的引用 ,放到 a.join 上的。覆盖原来的 join 方法

@seujzhang
Copy link

数组这个 a.join = a.shift; 没看懂啊

把 shift 方法的引用 ,放到 a.join 上的。覆盖原来的 join 方法

为啥a==1之后会执行join(shift)函数?

@jjeejj
Copy link
Contributor

jjeejj commented Mar 30, 2019

@seujzhang 执行 a ==1 会进行隐式转换

@seujzhang
Copy link

@seujzhang 执行 a ==1 会进行隐式转换

小白求教下,是不是这样的:在执行a==1的时候,会尝试对a进行隐式转换,此时隐式转换会调用Array的join方法,而此时join方法被shift覆盖,所以调用的实际上是shift方法,弹出1,然后相等,再弹出2相等,弹出3相等,最后console执行。

@quxww1
Copy link

quxww1 commented Apr 2, 2019

这个题目考察==的隐式转换吧

利用toString

let a = {
  i: 1,
  toString () {
    return a.i++
  }
}

if(a == 1 && a == 2 && a == 3) {
  console.log('1');
}

利用valueOf

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

if(a == 1 && a == 2 && a == 3) {
  console.log('1');
}

数组这个就有点妖了

var a = [1,2,3];
a.join = a.shift;
if(a == 1 && a == 2 && a == 3) {
  console.log('1');
}

ES6的symbol

let a = {[Symbol.toPrimitive]: ((i) => () => ++i) (0)};
if(a == 1 && a == 2 && a == 3) {
  console.log('1');
}

从 (a==1&&a==2&&a==3) 成立中看javascript的隐式类型转换

这个a.join = a.shift 是什么意思 还能这样子赋值麽。

@yu910709
Copy link

yu910709 commented Apr 3, 2019

第一反应想到的是a = console.log(1)😂😂

为什么总有一些让人眼前一亮的答案😂

@zeroone001
Copy link

zeroone001 commented Apr 8, 2019

对象转原始类型
Symbol.toPrimitive 优先级最高

var a = {
    i: 1,
    valueOf() {
        return a.i++;
    },
    toString() {
        return a.i++;
    },
    [Symbol.toPrimitive]() {
        return a.i++;
    }
}

if ( a == 1 && a == 2 && a == 3 ) {
  console.log(1);
}

@formattedzzz
Copy link

formattedzzz commented Apr 8, 2019

来一手另类的👋👋

Object.prototype.toString = (function () {
  var t = 1;
  return function () {
    return t++;
  }
})()
var a = {}
a == 1 && a == 2 && a == 3  // true

@Caitingwei
Copy link

var a = {
   value: 1,
   toString: function() {
     return a.value++;
   },
};
if(a == 1 && a == 2 && a == 3){
  console.log(1);
}
    

@zhoubendong
Copy link

第一反应想到的是a = console.log(1)

蔡徐坤行为-_-!!!

@zhoubendong
Copy link

第一反应想到的是a = console.log(1)joyjoy

为什么总有一些让人眼前一亮的答案

这操作属实有点优秀啊

@ShiJinlong1997
Copy link

var a = true;

@weblijingang
Copy link

let i = 1;
let a = new Proxy({},{
i:1,
get(){
return ()=> this.i++
}
})
console.log(a==1&&a==2&&a==3)

@gengruohai
Copy link

解释一下好吗?

@mongonice
Copy link

var a = {
    i: 1,
    toString () {
        return this.i++
    }
}

if (a == 1 && a == 2 && a == 3) {
    console.log('真棒')
}

@Jay214
Copy link

Jay214 commented Jul 27, 2019

为什么a==true不行?

@yygmind
Copy link
Contributor

yygmind commented Dec 16, 2019

var a = ?;
if(a == 1 && a == 2 && a == 3){
  console.log(1);
}

@whmax03
Copy link

whmax03 commented Dec 31, 2019

正好掘金文章有相关解释

@whosesmile
Copy link

看到答案瞬间懵逼...
这个东西反常识,写代码单元测试的人直接吐血...

@captain-xu
Copy link

数组这个 a.join = a.shift; 没看懂啊

数组隐式转换成字符串之前会执行一次join操作-> a.valueOf().join().toString()

@TaylerTao
Copy link

现在都推===和typescript了,还在考这些垃圾特性...

@fireairforce
Copy link

现在都推===和typescript了,还在考这些垃圾特性...

哈哈哈哈

@gylgyl
Copy link

gylgyl commented Apr 2, 2020

var a = {
  num: 1,
  valueOf() {
    return a.num++
  }
}
console.log(a == 1 && a == 2 && a == 3, '1-------')

var b = {
  num: 1,
  toString() {
    return b.num++
  }
}
console.log(b == 1 && b == 2 && b == 3, '2-------')

var c = {
  num: 1,
  [Symbol.toPrimitive](h) {
    return c.num++
  }
}
console.log(c == 1 && c == 2 && c == 3, '3-------')

var d = new Proxy(
  {},
  {
    i: 1,
    get: function() {
      return () => this.i++
    }
  }
)
console.log(d == 1 && d == 2 && d == 3, '4-------')

efun = {
  i: 1,
  get: function() {
    return efun.i++
  }
}
Object.defineProperty(global, 'e', efun)
console.log(e == 1 && e == 2 && e == 3, '5-------')

var f = [1, 2, 3]
f.join = f.shift
console.log(f == 1 && f == 2 && f == 3, '6-------')

var g = {
  i: 123,
  reg: /\d/g,
  valueOf() {
    return this.reg.exec(this.i)[0]
  }
}
console.log(g == 1 && g == 2 && g == 3, '7-------')

@cMYour
Copy link

cMYour commented Apr 7, 2020

@ihoneys
Copy link

ihoneys commented Apr 14, 2020

数组这个 a.join = a.shift; 没看懂啊

如何a是Array,a==1 会自动数据类型的转换,也就是调用a.join方法,而a.shift是deleteArray的第一元素并返回delete的元素,understand?

@qimiaowan
Copy link

来个骚的

var a = new Number()
a.valueOf = (a=>()=>a++)(1)
if ( a == 1 && a == 2 && a == 3 ) {
  console.log('1');
}

@ptylll
Copy link

ptylll commented Jun 10, 2020

var a = 1;
if(!(a == 1 && a == 2 && a == 3)){
 	console.log(1);
}

@cutie6
Copy link

cutie6 commented Jun 15, 2020

@XinJack console.log() 的返回值是 undefined

但也达到了打印 1 的目的啊

@jackchang2015
Copy link

jackchang2015 commented Jul 14, 2020

@seujzhang 执行 a ==1 会进行隐式转换

小白求教下,是不是这样的:在执行a==1的时候,会尝试对a进行隐式转换,此时隐式转换会调用Array的join方法,而此时join方法被shift覆盖,所以调用的实际上是shift方法,弹出1,然后相等,再弹出2相等,弹出3相等,最后console执行。

对,你打印一下a就看到了,实际上是給a添加一个join属性,这个属性就是shift方法,所以a.join是一个方法,隐士转换的时候调用a
的join()方法,而此时a自己有join属性了,就不会去Array原型链上找了,而a.join === Array.prototype.shift; 所以执行a.join()就相当于执行Array.prototype.shift方法,

@zengkaiz
Copy link

let i = 0
Object.defineProperty('window', 'a', {
  get:()=>{
     return ++i
 }
}

@weblijingang
Copy link

weblijingang commented Jul 22, 2020 via email

@jackchang2015
Copy link

var a = [1,2,3];
a.join = a.shift;
if(a == 1 && a == 2 && a == 3){
 	console.log(1);
}

//
var a = {
   i: 0,
   toString: function(){
        return this.i += 1;
   } 
};

if(a == 1 && a == 2 && a == 3){
 	console.log(1);
}

//
var a = {
   i: 0,
   valueOf: function(){
        return this.i += 1;
   } 
};

if(a == 1 && a == 2 && a == 3){
 	console.log(1);
}

//
Object.defineProperty(window, 'a', {

    get: function(){
        return this.value = this.value ? (this.value +=1  : 1;
}
});

if(a == 1 && a == 2 && a == 3){
 	console.log(1);
}

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

@MrLeihe
Copy link

MrLeihe commented Apr 22, 2021

来一手另类的👋👋

Object.prototype.toString = (function () {
  var t = 1;
  return function () {
    return t++;
  }
})()
var a = {}
a == 1 && a == 2 && a == 3  // true

覆盖原型还是不太好

@DemonKHH
Copy link

DemonKHH commented Apr 25, 2021

var a = a ? ++a : 1;
if(a == 1 && a == 2 && a == 3){
 	console.log(1);
}

// 下面的也能输出
if(a === 1 && a === 2 && a === 3){
 	console.log(1);
}

这样不香嘛

@zhelingwang
Copy link

zhelingwang commented May 8, 2021

    let times = 0;
    var a = {
      [Symbol.toPrimitive]: function () {
        return ++times;
      }
    };
    if (a == 1 && a == 2 && a == 3) {
      console.log(1);
    }

@Y-J-H
Copy link

Y-J-H commented May 30, 2021

最先想到的是get, set, 这样好像就没有var a了, 感觉有点偏题, 不过估计知识点应该是valueOf, toString, 哈哈哈

Object.defineProperty(window, 'a', {
  get: (function() {
    var i = 1
    return function () {
      return i++
    }
  })(),
  set: function(val) {
    return val
  }
})

if(a == 1 && a == 2 && a == 3){
  console.log(1);
}

@nxt-hj
Copy link

nxt-hj commented Jul 16, 2021

var a = (function b(num){
  b.valueOf=function(){return ++num}
  return b
})(0)

@Ha0ran2001
Copy link

为什么a==true不行?

Boolean和其他类型比较,先被转换为Number,true被转换成 1

@Ha0ran2001
Copy link

数组这个 a.join = a.shift; 没看懂啊

如何a是Array,a==1 会自动数据类型的转换,也就是调用a.join方法,而a.shift是deleteArray的第一元素并返回delete的元素,understand?

@ihoneys 啊?隐式类型转换还会调用 join 方法,我还以为就 toString 和 valueOf 呢,还有就是那个 拆箱时ToPrimitive,还会调用哪些方法?

@qinyakang
Copy link

var a = a ? ++a : 1;
if(a == 1 && a == 2 && a == 3){
 	console.log(1);
}

// 下面的也能输出
if(a === 1 && a === 2 && a === 3){
 	console.log(1);
}

这样不香嘛

这个在那个环境运行的,我咋没打印出来1 啊

@LeeRayno
Copy link

LeeRayno commented Sep 5, 2021

Object.defineProperty(window, 'a', {
    get: function() {
        return this.value += 1;
    }
});

要改下,不然报错。你这个挺好,可以做 ===

Object.defineProperty(window, 'a', {
    get: function() {
	if (this.value) {
	    return this.value += 1
	} else {
	    return this.value = 1;
	}
    }
});

精简一下代码:

Object.defineProperty(window, 'a', {
    get: function() {
          return this.value = this.value ? (this.value += 1) : 1;
    }
});

再精简一下:

Object.defineProperty(window, 'a', {
    get: function() {
          return this.value = (this.value || 0) + 1;
    }
});

@tchen-l
Copy link

tchen-l commented Sep 10, 2021

第一反应想到的是a = console.log(1)😂😂

这都没有进 if 语句啊😂

@Yuweiai
Copy link

Yuweiai commented Jul 13, 2022

(京东)下面代码中 a 在什么情况下会打印 1?

var a = ?;
if(a == 1 && a == 2 && a == 3){
 	console.log(1);
}
var a = {
  value: 1,
  toString() {
    return this.value++
  }
};

if(a == 1 && a == 2 && a == 3){
 	console.log(1);	// 1
}
var a = {
	arr: [1,2,3],
	toString: function() {
		return  this.arr.shift();
	}
};

if(a == 1 && a == 2 && a == 3){
 	console.log(1);	// 1
}
var a = {
	value: [1,2,3],
	toString: function() {
		return this.value.shift();
	},
  valueOf() {
    return 0
  }
};

console.log(a == 0)	// true

if(a == 1 && a == 2 && a == 3){
  console.log(1);
}
var a = {
	value: [1,2,3],
	toString: function() {
		return this.value.shift();
	},
  valueOf() {
    return {}
  }
};


if(a == 1 && a == 2 && a == 3){
  console.log(1);	// 1
}
var a = {
	value: [1,2,3],
	toString: function() {
		return {}
	},
  valueOf() {
    return {}
  }
};

// TypeError: Cannot convert object to primitive value
if(a == 1 && a == 2 && a == 3){
  console.log(1);
}
  1. 确定两个变量是否相等是编程中的一个非常重要的操作
    • 在比较字符串、数值和布尔值的相等性时,问题还比较简单;但在涉及到对象的比较时,问题就变得复杂了
    • 最早的ECMAScript中的相等和不等操作符会在执行比较之前,先将对象转换成相似的类型。后来,有人提出了这种转换到底是否合理的质疑
    • 最后,ECMAScript的解决方案就是提供两组操作符:
      • 相等不相等:先转换再比较
      • 全等不全等:仅比较而不转换
  2. 相等(==)和不相等(!=)在转换不同的数据类型时,遵循下列基本规则:
    • 如果有一个操作数是布尔值,则先将其转换为数值;(这也是为什么a = true不行的原因)
    • 如果有一个操作数是字符串,另一个操作数是数值,则先将字符串转换为数值
    • 如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较;**如果valueOf()也得不到基本类型值,则会调用toString();**如果toString()也得不到基本类型值,则会报错:TypeError: Cannot convert object to primitive value

@Lete114
Copy link

Lete114 commented Jul 21, 2022

var a = 1
if(a == 1 && ++a == 2 && ++a == 3){
  console.log(1);
}

@JDongKhan
Copy link

估计设计语言的时候,也没想到被这群屌人玩的这么花。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests