自学习前端以来,陆陆续续遇见很多短小令人惊讶的js代码,固有了专门开一片日记来记录这些代码的想法。借此提高写代码的姿势和深度理解JavaScript。
1.JavaScript中 (a ==1 && a== 2 && a==3) 可能为 true 吗?
来自Stack Overflow的一个问题:链接
国外面试题,Nothing is impossible.
解决方案1:
自定义 toString(或者 valueOf)方法,每次调用改变一次返回值,从而满足判断条件。
const a = {
i: 1,
toString: function () {
return a.i++;
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('Hello World!');
}
tostring()属于Object对象,当使用 == 时,如果两个参数的类型不一样,那么 JS 会尝试将其中一个的类型转换为和另一个相同。在这里左边对象,右边数字的情况下,会首先尝试调用 valueOf(如果可以调用的话)来将对象转换为数字,如果失败,再调用 toString。
第二个方法,有点像障眼法,=-=:
var aᅠ = 1;
var a = 2;
var ᅠa = 3;
if(aᅠ==1 && a== 2 &&ᅠa==3) {
console.log("Why hello there!")
}
注意在if语句(我从你的问题中复制)怪异的间距。 这是半角Hangul(即那些不熟悉的韩语),它是一个Unicode空格字符,不被ECMA脚本解释为空格字符 - 这意味着它是一个标识符的有效字符。 因此,有三个完全不同的变量,一个是在一个之后的Hangul,另一个是前一个,最后一个只有一个。 为了便于阅读,用_替换空格,相同的代码如下所示:
var a_ = 1;
var a = 2;
var _a = 3;
if(a_==1 && a== 2 &&_a==3) {
console.log("Why hello there!")
}
哈哈哈,我一般还通过切换半角全角符号方便在Markdown里做段落的空格处理。
还有一种解决方法就是js的with语句,把对象的作用域的范围明确出来(听说with语句缓慢)
var i = 0;
with({
get a() {
return ++i;
}
}) {
if (a == 1 && a == 2 && a == 3)
console.log("wohoo");
}
还有很多办法来解决这个,感兴趣自己可探究。
2.JavaScript合并数组
第一种方法
ES6之前,
// `b` onto `a`:
a.push.apply( a, b );
a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
// or `a` into `b`:
b.unshift.apply( b, a );
b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
看apply的文档;
第二个参数:argsArray 一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或
undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。
所以
let a = [1,2,3],b=[4,5,6];
a.push.apply(a,b);
实质上会将b中三个元素4,5,6当作a.push的参数,这里的a不是apply左边的a,而是传给apply的第一个参数。前面的a只是为了使用push方法,这里的fun函数就是push,换句话说,apply会将第二个类数组参数拆分成一个个单独项。
而与之对应的有个call方法。
let a = [1,2,3];
a.push.call(a,4,5,6);
虽然支持超过2个参数,但需要将参数都列出来,在数组操作上比apply要弱上许多。
第二种方法
ES6后有了扩展运算符很方便
let a = [1,2,3],b=[4,5,6];
a.push(...b) // 6
a // [1, 2, 3, 4, 5, 6]
第三种方法
用reduce函数,文档:
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
合并操作:
// `b` onto `a`:
a = b.reduce( function(coll,item){
coll.push( item );
return coll;
}, a );
a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
// or `a` into `b`:
b = a.reduceRight( function(coll,item){
coll.unshift( item );
return coll;
}, b );
b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
3.万能变量类型检测
1.首先想到的肯定是用typeof 检测
2.利用toString()检测:
通过toString() 来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数,称为thisArg。
如果在控制台输入:
var a = ‘111’
Object.prototype.toString(a)
返回:”[object Object]”
Object.prototype.toString(a) 中toString 的 this 是 Object.prototype,会返回[Object ],a 是 toString 的参数。 Object.prototype.toString.call(a) 中toString 的 this 是 a,没有参数。
变量检测:
var toString = Object.prototype.toString;
toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]
//Since JavaScript 1.8.5
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
很强大吧,undefined和null都能检测出来。。