-
Notifications
You must be signed in to change notification settings - Fork 208
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
JavaScript问题集锦 #2
Comments
7. 原型链导致的属性更改无效问题: 看下面的代码,为什么 var proto = Object.create({}, {
x: {
value: 1,
writable: false
}
});
var obj = Object.create(proto);
obj.x = 100; // 无效,strict mode下报错: Uncaught TypeError
console.log(obj.x); // 1 原因:
本题中, 8. 位操作符问题: 实现浮点数转整数,或者说取出数字的整数部分。比如 解决: function convertToInt(num) {
return num >> 0;
}
convertToInt(-Math.PI); // -3
convertToInt(12.921); // 12 原因: 没有什么高达上,就是神奇的位操作符:有符号右移
本题利用了有符号右移会将左操作数转换为32位整数。 补充: 同理, 9. IEEE-754精度问题问题: 原因: 所有使用IEEE-754数字实现的编程语言都有这个问题。
那么你一定想要比较相加后的结果和预期数字怎么办?宽容比较,即允许一定误差,这个误差值一般是 update 2017-02-13: |
10. Function.prototype.call/apply 的 this 问题问题: 下列情况中 function nsm() {console.log(this);}
nsm(); // Window{top: xxxx}
nsm.call(null/undefined); // Window{top: xxxx}
nsm.call(1); // Number {[[PrimitiveValue]]: 1}
function sm() {'use strict'; console.log(this);}
sm(); // undefined
sm.call(null); // null
sm.call(undefined); // undefined
sm.call(1); // 1 原因: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
非严格模式下, 严格模式下, 11. 给基础类型添加属性无效问题: 为什么给基础类型添加属性不报错但又无效? var num = 1;
num.prop = 2;
num.prop // undefined 原因: Property Accessors规范 https://es5.github.io/#x11.2.1:
GetValue规范 https://es5.github.io/#x8.7.1:
最后可知, 12. 数组的展开/扁平问题: function flatten(arr) {
if(!isArray(arr) || !arr.length) {
return [];
} else {
return Array.prototype.concat.apply([], arr.map(function(val) {
return isArray(val) ? flatten(val) : val;
}));
}
function isArray(arr) {
return Object.prototype.toString.call(arr).slice(8, -1).toLowerCase() === 'array';
}
}
flatten([1,2,[2,3,[4,5]]]);
// [1, 2, 2, 3, 4, 5] 另外,看到一种方法:利用 |
13.
|
14.
|
15.
|
16. 找出字符串中出现最多的字母这个问题看起来用到的地方挺多,至少我遇到过不止一次,索性在这里讲一讲。先具体描述下问题: 假设字符串 最先想到的解法是用map纪录每个字符的次数,然后找出最多的即可: function getMaxNumberOfChar(str) {
return (str + '').split('').reduce(function(pre, cur, index, arr) {
cur in pre ? pre[cur]++ : (pre[cur] = 1);
pre[cur] > pre.value && (pre.char = cur, pre.value = pre[cur]);
return pre;
}, {value: 0});
}
getMaxNumberOfChar('ababccdeajxac') // Object {value: 4, a: 4, char: "a", b: 2, c: 3…} 此外,可以考虑用正则来辅助处理: function getMaxNumberOfChar(str) {
return (str + '').split('').sort().join('').match(/(\w)\1*/g).reduce(function(pre, cur) {
return cur.length > pre.value ? {value: cur.length, char: cur[0]} : pre;
}, {value: 0})
}
getMaxNumberOfChar('ababccdeajxac') // Object {value: 4, char: "a"} |
17.
|
18. 一个函数柯里化问题及更多C君出了这样一个题,要求实现
第一眼,这不是函数柯里化吗,小case,然后我挥笔写下: function sum(item) {
var cur = item;
var inner = function(next) {
return next == null ? cur : (cur += next, inner);
};
return item == null ? undefined : inner;
} 运行下: perfect! 然后我看了看答案,又看了看题目 😕 ❓ 好吧,题目根本没有最后的 function sum(item) {
var cur = item;
var inner = function(next) {
if (next != null) cur += next;
return inner;
};
inner.toString = function() {
return cur;
}
return inner;
} 如上,改写 |
19. 运算符优先级问题普通的运算符优先级对大家应该不成问题,另外也推荐用括号来明确运算符优先级和代码意图,写出更可读的代码。 但之所以有这个问题,是涉及到 问题: var str = 'why I am ' + typeof + ''; // so what is str?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
|
20. Prefix Increment Operator(
|
21. 你真的了解
|
前端面试题,利用给定接口获得闭包内部对象 |
@rambo-panda 谈不上违背,从闭包中获取数据,可以加深对闭包的理解。 拿来面试可以考察一些原理,对新手而言,不看这些也是好的,免得混淆其它东西。 |
超棒! |
可以理解,有点难. |
第9题浮点数精度的问题可以用 |
@Leonard-Peng 感谢提醒,的确内置了,是在
|
22. 异步的
|
请问是否可以转载呢?会在文章开头注明作者和出处 |
@MRLP0524 可以 |
第3个原文的评论解释的挺好的 |
23.
|
24. JavaScript 中参数是值传递还是引用传递?https://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language --- stackoverflow 有同样的问题,高票回答一针见血: JavaScript 既不是值传递,也不是引用传递,而是 call by sharing . function changeStuff(a, b, c)
{
a = a * 10;
b.item = "changed";
c = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num); // 10
console.log(obj1.item); // changed
console.log(obj2.item); // unchanged 如 demo 所示,假设:
由以上两点可知,JavaScript 既不是值传递 (复制值),也不是引用传递 (可以直接操作作为参数的变量),而是 call by sharing。 那么什么是 call by sharing?
结合下面 c 语言的例子总结下: #include <stdio.h>
// 传引用
void log(int *p1, int *p2){
printf("%#X, %#X\n", p1, p2);
}
// 传值
void log2(int p1, int p2) {
printf("%#X, %#X\n", &p1, &p2);
printf("%d, %d\n", p1, p2);
}
int main(){
int a = 66, b = 99;
printf("%#X, %#X\n", &a, &b);
log(&a, &b);
log2(a, b);
printf("a = %d, b = %d\n", a, b);
return 0;
}
/*
0X5B769758, 0X5B769754
0X5B769758, 0X5B769754
0X5B76972C, 0X5B769728
66, 99
a = 66, b = 99
*/ 如上例所示:
|
|
@ChenYouping 你说的没问题。Java 中传参数的本质是赋值操作,primitive 就是本身的值,object 就是内存地址。 不过鉴于C语言的传引用 ( 补充阅读:
|
博主您好, |
@TaroSunn 应该是chrome新版本跟以前的处理逻辑不一致了。 |
从原博客迁移过来(有更改),并将保持更新。
关于JavaScript,工作和学习过程中遇到过许多问题,也解答过许多别人的问题。这篇文章记录了一些有价值的问题。
1. 对象字面值不能正确解析
问题:
{a:1}.a
报错,错误Uncaught SyntaxError: Unexpected token .
。解决:
原因:
MDN: Object literals
简单说,就是声明对象字面值时,语句开头不应该用
{
,因为js解释器会认为这是语句块(block
)的开始。同理,类似问题
{ name: "mc", id: 1 }
会报错Uncaught SyntaxError: Unexpected token :
也是这个道理。({ name: "mc", id: 1 })
即可正确解析。但稍注意下,{name: "mc"}
是不会报错的,它等同于name: "mc"
,并返回一个字符串"mc"
。2. 数字的点操作符
问题:
123.toFixed(2)
报错,错误Uncaught SyntaxError: Unexpected token ILLEGAL
解决:
原因:
很简单,js解释器会把数字后的
.
当做小数点而不是点操作符。3. 连等赋值问题
问题:尝试解释下连等赋值的过程。下面的代码为什么是这样的输出?
原因:
我们可以先尝试交换下连等赋值顺序(
a = a.x = {n: 2};
),可以发现输出不变,即顺序不影响结果。那么现在来解释对象连等赋值的问题:按照es5规范,题中连等赋值等价于
a.x = (a = {n: 2});
,按优先获取左引用(lref
),然后获取右引用(rref
)的顺序,a.x
和a
中的a都指向了{n: 1}
。至此,至关重要或者说最迷惑的一步明确。(a = {n: 2})
执行完成后,变量a
指向{n: 2}
,并返回{n: 2}
;接着执行a.x = {n: 2}
,这里的a
就是b
(指向{n: 1}
),所以b.x
就指向了{n: 2}
。搜索此题答案时,颜海镜的一篇博客关于此题也有讲述,不过没有讲清楚(或许是我没有领会 :P)。
*以 AST 的角度更清晰地解释此题(2017-11-06)*
esprima 提供解析 JS 到 AST 的功能,我们可以借此看一下这段代码在引擎眼里到底是什么。(其实 node 从 8 开始开始支持编译 JS 到 AST 了 (V8 ignition interpreter),不过 node 好像没有提供接口给我们使用)。
下面是我拿到的上面代码的 AST:
可以清晰地得到,代码等价于:
a.x = (a = {n: 2});
。然后核心的知识点是:引用解析发生在实际赋值之前 。4. 逗号操作符
问题: 下面的代码返回什么,为什么?
原因:
MDN逗号操作符:
即逗号操作符会从左到右计算它的操作数,返回最后一个操作数的值。所以
(temp.foo, temp.foo)();
等价于var fun = temp.foo; fun();
,fun
调用时this
指向window
,所以返回20。5. parseInt传入数字
问题: parseInt传入数字时为什么有以下输出?
原因:
parseInt(arg)
时会调用arg.toString()
。6. 前端面试题,利用给定接口获得闭包内部对象
问题: 前端面试题,利用给定接口获得闭包内部对象
在不改变上面的代码情况下, 怎么得到原有的 person 对象?
解决:
但如果加上
person.__proto__ = null
,目前还没找到解决方法。The text was updated successfully, but these errors were encountered: