先看个有意思的面试题:
要求:用JS写个函数add可以实现以下的功能。
add(num1)(num2)(num3)...; / /注意这里是省略号哟,无限
add(10)(10) = 20;
add(10)(20)(50) = 80;
add(10)(20)(50)(100) = 180;
add(10, 20, 50, 100) = 180;
add(10, 20)(50, 100) = 180;
function add(...parm) {
// ES6的方式拿参数值,这样拿到的 parm 相当于
// var parm = Array.prototype.slice.call(arguments);
// 不传值的情况下 parm 为 []
var sum = 0;
for (let i = 0; i < parm.length; i++) {
sum += parm[i];
}
var tmp = function (...val) {
for (let i = 0; i < val.length; i++) {
sum += val[i];
}
return tmp;
};
tmp.toString = function () {
return sum;
};
return tmp;
};
alert(add(10)(20)(50)); // 80
对象使用和属性
JavaScript 中所有变量都可以当作对象使用,除了两个例外 null
和 undefined
。
false.toString(); // 'false'
[1, 2, 3].toString(); // '1,2,3'
function Foo(){}
Foo.bar = 1;
Foo.bar; // 1
一个常见的误解是数字的字面值(literal)不能当作对象使用。这是因为 JavaScript 解析器的一个错误, 它试图将点操作符解析为浮点数字面值的一部分。
2.toString(); // 出错:SyntaxError
有很多变通方法可以让数字的字面值看起来像对象。
2..toString(); // 第二个点号可以正常解析
2 .toString(); // 注意点号前面的空格
(2).toString(); // 2先被计算
每个对象的toString和valueOf方法都可以被改写,每个对象执行完毕,如果被用以操作JavaScript解析器就会自动调用对象的toString或者valueOf方法,举栗子:
// 我们先创建一个对象,并修改其toString和valueOf方法
var obj = {
i: 10,
valueOf: function () {
console.log('执行了valueOf()');
return this.i + 20;
},
toString: function () {
console.log('执行了toString()');
return this.valueOf() + 20;
}
};
// 当我们调用的时候:
alert(obj); // 50 执行了toString() 执行了valueOf()
alert(+obj); // 30 执行了valueOf()
alert(obj > 40); // false 执行了valueOf()
alert(obj == 30); // true 执行了valueOf()
alert(obj === 30); // false
// 最后这个未输出任何字符串,个人猜想是这样的:全等比较时,js解析器直接先判断类型是否一样,明显一个是Object,一个是Number,所以直接不相等,根本不需要再去求值了。
由上可以看出,虽然我们没有调用obj的任何方法,但是要使用obj进行操作时,好像js解析器自动帮我们调用了其toString或valueOf方法。
接下来就是探究什么时候执行的是toString方法,什么时候执行的是valueOf方法了。大致猜这样:如果做加减乘除、比较运算的时候执行的是valueOf方法,如果是需要具体值呢就执行的是toString方法。
更严谨的实验: https://www.cnblogs.com/aNd1coder/archive/2013/03/09/2951959.html
参考:
https://www.cnblogs.com/barrior/p/4598354.html
http://www.cnblogs.com/rubylouvre/archive/2010/10/01/1839748.html
http://zjuwwq.gitbooks.io/jump_javascript/content/data_types/type_conversion.html
网友评论