写在前面的话
本人不是高手, 也是小白一只. 在学习的过程中, 总是反复的遗忘, 记忆, 练习, 遗忘.. 因此决定把走过的坑, 以及经历的笔试开始慢慢的总结, 会不断的更新和添加, 原文地址在 github, 觉得不错的小伙伴, 记得给个 star 哦, 共同进步~~
更新地址: 传送门 https://github.com/forrany/web-Project/blob/master/前端面试&错题指南.md
前端面试 & 笔试 & 错题指南
CSS 相关
1. display:none 与 visibility:hidden 的区别 (2018 拼多多前端笔试真题)
答案: 在视觉效果上, 两者是相同的, 但是对于操作 dom 上是不同的 . dispaly:none 会让 dom 的整个宽, 高等相关位置元素失效, 整个消失; visibility:hidden 只是让该元素不可见, 但是 width 以及原有位置是不会改变的
javascript
1. 基本问题
1) 是否可以使用
typeof bar === 'object'
来检测 bar 是不是 object 类型, 有和风险?
答案: 有风险, js 的基本数据类型有 String Number Boolean undefined null 和一种复杂数据类型 object(ES6 新增了 symbol).
对于复杂数据类型 object, 其实 typeof null 返回的也是 object, 因为本质上 null 就是一个占位用的对象. 另一方面, 数组 Array 也不能用 typeof 检测数据类型, 因为同样会返回 object.
因此, 如果想要检测 bar 是不是 object, 可以这样子:
- console.log((bar !== null) && (tiopnuiop[yuiop[]\\]poi456/ypeof bar ==='object'))
- // 当然, 如果认为 function 也是 object, 可以用下面的语句
- console.log((bar !== nul)&& (typeof bar ==='object')||(typeof bar ==='function'))
复制代码
除此以外, 还有比如 Array 的情况, 因为 Array 也会返回 object, 如果我们不像让 Array 被认为是 Object, 就必须真正的认清 Array, 人情 Array 的方法有:
- console.log( bar instanceof Array) // 如果数组, 返回 true
- console.log( Array.isArray(bar)) //ES5 方法
- console.log( Ojbect.prototype.toString.call(arr) === '[object Array]')
复制代码
2) 以下两个函数是否等价
- function foo1()
- {
- return {
- bar: "hello"
- };
- }
- function foo2()
- {
- return
- {
- bar: "hello"
- };
- }
复制代码
答案: 不等价!! 注意, 第二个函数返回的是 undefined
- console.log(foo1()); // {bar : "hellp"}
- console.log(foo2()); // undefined
复制代码
这也是为什么函数返回对象时, 或写大括号时, 把 {写在一边, 因为第二个函数 js 会默认 return 后面返回的东西 (是空), 等价于
- return undefined
- {xxx}
- // 后面当然, 当然是写了也白写
复制代码
3) NaN 是什么? 它是什么类型? 如何检测一个变量是不是 NaN?
答案: NaN 即 Not A Number, 但实际上它是 Number 类型 typeof NaN 将会返回 Number. 这个东西比较厉害, 因为
NaN === NaN //false
复制代码
你会发现, 它自己都不等于它自己, 因此判断变量是否是它, 不能使用 ===. 可以使用 isNaN 方法
- // 检查变量是否是 nan
- isNaN(bar);
- Object.is(bar,NaN); //ES6 方法, 这个方法会修正 JS 中的一些小 bug
复制代码
Object.is() 方法, 要求严格相等, 且 Object.is(NaN,NaN) 会返回 true
2. 作用域相关问题
以下程序的输出是什么:
- (function(){
- var a = b = 3;
- })();
- console.log("a defined?" + (typeof a !== 'undefined'));
- console.log("b defined?" + (typeof b !== 'undefined'));
复制代码
答案: a defined? false
b defined? true
理解这道题的核心在于如何理解 var a = b = 3 这句话, 实际上这句话等于
var a;
b = 3;
复制代码
这样子, 实际上, b 是声明在了全局变量中 (编译器在预编译帮你声明了, 然而在严格模式下是不行的) a 是局部变量, 所以在函数之外是没有定义的.
3.this & 对象 & 数组
1) 下面程序输出是什么
- var myObject = {
- foo: "bar",
- func: function() {
- var self = this;
- console.log("outer func: this.foo =" + this.foo);
- console.log("outer func: self.foo =" + self.foo);
- (function() {
- console.log(this);
- console.log("inner func: this.foo =" + this.foo);
- console.log("inner func: self.foo =" + self.foo);
- }());
- }
- };
- myObject.func();
- // 答案
- outer func: this.foo = bar
- outer func: serl.foo = bar
- inner func: this.foo = undefined
- inner func: self.foo = bar
复制代码
分析: 搞清楚 this 的指向. 记住以下几种规则
谁调用, this 指向谁 xxx.fun()
new 一个对象, this 指向实例本身 var c = new fun()
使用 call/apply/bind 修改 this 指向.
看题目, outer func 显然是第一种情况, 谁调用, this 指向谁, 这个时候都是 myOjbect. 而在立即执行函数中, 在这里 this 是没有进行绑定指向的, 自然从属于 window, 所以这里 this.foo 是 undefied
补充关于箭头函数的 this
- function a() {
- return () => {
- return () => {
- console.log(this)
- }
- }
- }
- console.log(a()()())
复制代码
注意: 箭头函数其实是没有 this 的, 这个函数中的 this 只取决于他外面的第一个不是箭头函数的函数的 this. 在这个例子中, 因为调用 a 符合前面代码中的第一个情况, 所以 this 是 window. 并且 this 一旦绑定了上下文, 就不会被任何代码改变.
2) 数组的 filter, 以下输出结果是什么 (2018 拼多多前端原题)
- var arr = [1,2,3];
- arr[10] = 9;
- arr.filter((item)=> {
- return item === undefined?
- })
- // 答案
- []
复制代码
解析: 是的, 答案的确是 [], 不是 [undefined x 7]. 首先, 看下前两句执行后, arr 是什么
- console.log(arr)
- //[1,2,3, emptyx7, 9]
- console.log(arr[5])
- //undefined
复制代码
从上面结果可以看出, 的确中间未定义的 (显示为 empty 的是 undefined). 那么, filter 之后, 不是应该返回为 undefined 的数据吗?
是的, 但是, 当数组中都是 undefined 时, 数组就是空, 或者说 [empty x 7] === []
4. JS 小数计算不准确的 bug
以下代码返回值是什么
- console.log(0.1 + 0.2);
- console.log(0.1 + 0.2 == 0.3);
- // 答案: 0.30000000000000004
- false
复制代码
解析: 详细的解析见连接, 这里说一下解决办法 0.1+0.2 != 0.3 https://segmentfault.com/a/1190000015051329?utm_source=index-hottest
- // 解决办法
- parseFloat((0.1+0.2).toFixed(10));
复制代码
5. 算法 / 思路相关
1) 讨论实现判断变量是否是整数的函数 isInter(x) 的实现
答案: 在 ES6 中, 是有现成的方法 Number.isInteger 可以使用的. 如果自己实现, 思路是什么呢
- //1 异或运算
- function isInter(x) {
- return x ^ 0 === x
- }
- //2 取整
- return Math.round(x) === x // 同样可以用 floor ceil
- // 取余
- return (typeof x === 'number')&&(x % 1 === 0)
复制代码
2) 写一个 sum 方法, 可以实现以下两种调用方式
- console.log(sum(2,3)) //5
- console.log(sum(2)(3)) //5
复制代码
答案:
- // 方法 1
- var sum = function(x,y) {
- if(y === undefined) {
- return function(y) {
- return x + y;
- }
- }else {
- return x + y;
- }
- }
- // 方法 2
- var sum = function(x){
- if( arguments.length === 1) {
- return function (y) {
- return x + y;
- }
- } else {
- console.log('here');
- return arguments[0] + arguments[1];
- }
- }
复制代码
3) 使用递归的方法, 将 obj 变为 obj2 的格式 (拼多多 2018 前端笔试真题)
- obj = [
- {id:1,parent:null},
- {id:2,parent:1},
- {id:3,parent:2}
- ]
- obj2 = {
- obj:{
- id: 1,
- parent: null,
- child: {
- id: 2,
- parent: 1,
- child: {
- id: ,3,
- parent: 2
- }
- }
- }
- }
复制代码
来源: https://juejin.im/post/5b549b965188251acd0f2ab1