Skip to content

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

@zpzxgcr

Description

@zpzxgcr

题目如下

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);
}

Activity

Yanhua67

Yanhua67 commented on Mar 21, 2019

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

jefferyE commented on Mar 21, 2019

@jefferyE

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

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

Moriarty02 commented on Mar 21, 2019

@Moriarty02

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

利用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

win7killer commented on Mar 21, 2019

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

win7killer commented on Mar 21, 2019

@win7killer
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

jjeejj commented on Mar 21, 2019

@jjeejj
Contributor
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

HankXu commented on Mar 21, 2019

@HankXu

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

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

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

XinJack commented on Mar 21, 2019

@XinJack

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

jiyuzhuang

jiyuzhuang commented on Mar 22, 2019

@jiyuzhuang

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

RicoLiu

RicoLiu commented on Mar 27, 2019

@RicoLiu

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

leehomeok

leehomeok commented on Mar 28, 2019

@leehomeok

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

jjeejj

jjeejj commented on Mar 28, 2019

@jjeejj
Contributor

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

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

seujzhang

seujzhang commented on Mar 29, 2019

@seujzhang

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

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

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

jjeejj

jjeejj commented on Mar 30, 2019

@jjeejj
Contributor

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

seujzhang

seujzhang commented on Mar 30, 2019

@seujzhang

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

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

40 remaining items

weblijingang

weblijingang commented on Jul 22, 2020

@weblijingang
jackchang2015

jackchang2015 commented on Jul 30, 2020

@jackchang2015
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

MrLeihe commented on Apr 22, 2021

@MrLeihe

来一手另类的👋👋

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

覆盖原型还是不太好

DemonKHH

DemonKHH commented on Apr 25, 2021

@DemonKHH
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

zhelingwang commented on May 8, 2021

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

Y-J-H commented on May 30, 2021

@Y-J-H

最先想到的是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

nxt-hj commented on Jul 16, 2021

@nxt-hj
var a = (function b(num){
  b.valueOf=function(){return ++num}
  return b
})(0)
Ha0ran2001

Ha0ran2001 commented on Aug 19, 2021

@Ha0ran2001

为什么a==true不行?

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

Ha0ran2001

Ha0ran2001 commented on Aug 19, 2021

@Ha0ran2001

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

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

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

qinyakang

qinyakang commented on Aug 30, 2021

@qinyakang
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

LeeRayno commented on Sep 5, 2021

@LeeRayno
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

tchen-l commented on Sep 10, 2021

@tchen-l

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

这都没有进 if 语句啊😂

Yuweiai

Yuweiai commented on Jul 13, 2022

@Yuweiai

(京东)下面代码中 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

lete114 commented on Jul 21, 2022

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

JDongKhan commented on Aug 7, 2023

@JDongKhan

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

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @whosesmile@smalike@JDongKhan@aeolusheath@win7killer

        Issue actions

          第 38 题:下面代码中 a 在什么情况下会打印 1? · Issue #57 · Advanced-Frontend/Daily-Interview-Question