2024年【JS错题锦集】记录一下常考易错知识点(2),大厂面试注意什么

最后

小编综合了阿里的面试题做了一份前端面试题PDF文档,里面有面试题的详细解析

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

虽只说了一个公司的面试,但我们可以知道大厂关注的东西并举一反三,通过一个知识点延伸到另一个知识点,这是我们要掌握的学习方法,小伙伴们在这篇有学到的请评论点赞转发告诉小编哦,谢谢大家的支持!

var myObject = {

foo: “bar”,

func: function() {

var self = this;

console.log(this.foo);

console.log(self.foo);

(function() {

console.log(this.foo);

console.log(self.foo);

}());

}

};

myObject.func();

A.bar

bar

bar

bar

B.bar

bar

bar

undefined

C.bar

bar

undefined

bar

D.undefined

bar

undefined

bar

把这题做对了,我就又是最靓的仔了!<( ̄︶ ̄)↗[GO!]

判断this指向的小技巧:

- 哪个对象拥有了这个函数,this就是这个对象的指代

程序的最后,运行的是myObject对象下的func方法,也就是myObject.func();,说明在func作用域下,this指代的是myObject对象

- 匿名函数的执行环境具有全局性

匿名函数里的this一般指向window

有了这两个知识点,我们就可以来做这道题了

var myObject = {

foo: “bar”,

func: function() {

var self = this;

// 此处的this指的是myObject,而self则保存了这this指向

// 后续出现self,我们就知道,只是是指myObject

console.log(this.foo); // this指的是myObject,输出"bar"

console.log(self.foo); // self指的是myObject,输出"bar"

(function() { // 匿名函数,this指向window对象

console.log(this.foo); // this指的是window,输出undefined

console.log(self.foo); // self指的是myObject,输出"bar"

}());

}

};

myObject.func();

答案:C

2.prototype和__proto__

=========================

单选题:下面说法错误的是:

A. 每个对象都具有一个名为__proto__的属性

B. 每个对象都具有一个名为prototype的方法

C.每个对象的__proto__属性指向自身构造函数的prototype

D.对象不具有prototype属性,只有函数才有prototype属性

这个知识点,貌似比较深奥,也比较有争议。看了评论区各位大佬和网络的解答,觉得本人目前还没有能力理解透彻

此处贴上某位大佬的一个解答,建议点开详情看评论回复,here

还有一位大佬的良心解答,应该是比较完善的:here

呜呜呜,太强了,忍不住崇拜一下

在这里插入图片描述

大佬在最后贴心地总结了一下,截图如下:

在这里插入图片描述

式子再写一遍:

函数创建的对象.__proto__ === 该函数.prototype

该函数.prototype.constructor===该函数本身

例子:

function Foo() {…}

let f1 = new Foo();

重点:f1.__proto__ === Foo.prototype

回到题目

在这里插入图片描述

比较有争议的是这两个疑点:

“函数也是对象”——D咋办?

“null是对象?null没有__proto__” ——A咋办?

我的想法:

  • 在这道题中,函数和对象应该是特意区分了一下,为了辅助区别__proto__和prototype
  • 由于typeof null返回“object”是一个历史错误(JS的发明者Brendan Eich自己也是这样说的),只是因为要保持语言的兼容性而维持至今
而且,null属于基本数据类型之一,因此,我倾向于,用”null不是对象“来解释这道题  
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210613114300265.png)

再根据大佬的文章,这道题就可以做出来了:

  • 对象都有__proto__属性,A选项正确;
  • 函数独有一个prototype,B选项错误,D选项正确;
  • 函数创建的对象.__proto__ === 该函数.prototype,C选项正确;

答案:B


这个知识点比较重要,所以把遇到的题都整理出来,便于加深理解

不定项选择题:下列说法正确的是():

A. 每个JS对象一定对应一个原型对象,并从原型对象继承属性和方法

B. 对象的__proto__指向自己构造函数的prototype

C.Object.prototype. __proto__=== null,说明原型链到Object.prototype终止

D.表达式 Function.prototype.__proto__.__proto__ === null 的运行结果为true

根据大佬的文章,这道题BCD选项均正确

B选项是对的,根据该选项,可以知道Object.create(null)得到的对象obj,没有原型对象,因此选项A错误

答案:BCD

3.call与apply对比

==============

单选题1:下面有关JavaScript中call和apply的描述,错误的是?

A.apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入

B.call与apply都属于Function.prototype的一个方法,所以每个function实例都有call,apply属性

C.两者传递的参数不同,call函数第一个参数都是要传入给当前对象的对象,apply不是

D.call传入的则是直接的参数列表,call方法可将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新内容

看起来有点绕,别担心,绕着绕着就出去了😜仔细看题就好~

前面已经讲到,在ES5语法中,this指向的判断规则是:哪个对象拥有了这个函数,this就指向这个对象

而call和apply就是用于:改变this指向为自己特定的对象,并且这两个方法是非继承而来的(Function.prototype.call()和Function.prototype.apply()),每个函数都包含这两个方法,这是两个方法的基本概念~

apply语法:fun.apply([thisObj [,argArray] ]);

call语法:fun.call([thisObj[,arg1 [,arg2 [,…,argn]]]]);

使用了apply和call之后,this指向了thisObj,即第一个参数均是要特定的this对象,是传入给当前函数(对象)的对象

apply的第二个参数是一个数组,call则是一个个列出参数的

在这里插入图片描述

这是官方给出的两者区别~

到此,我们已经可以解题了,答案选C,apply和call接收不同的参数在于后面的参数,apply接收数组,call逐个接收;第一个参数的用法是一致的,都是this指向


单选题2:请阅读以下代码,该代码在浏览器中执行,输出的日志结果是什么?

A.undefined

B.window

C.console

D.obj

var obj = {};

obj.log = console.log;

obj.log.call(console,this);

分析:

  • 将console.log的功能复制给obj.log,因此后者功能也是输出;

  • call将log方法的执行权给了window.console,要求它输出this,所以绕了个弯,求的是

console.log(this); // 输出window对象

答案:B

评论区有大佬提到了严格模式,放上官网链接:here

4.强制转换、隐式转换

===========

4.1 双等号==


不定项选择题:以下哪些表达式的结果为true?

A. undefined == null

B. isNaN(“100”) ——不好意思,isNaN乱入了,见谅

C. parseInt(“1a”) === 1

D. [ ] instanceof Array

答友精彩解析:

A. undefined == null 为true; undefined===null为false

B. 当传入NaN或能被转换成NaN的值(不能转成Number型数据的字符串、对象、undefined等非数字值),isNaN会返回true,即使是isNaN(“true”)。传入"100"会被先转成Number–>100,不为NaN,因此返回false

C. parseInt(“1a”)只会解析前面是数字的部分,即只解析"1",parseInt(“1a1”) === 1也为true

D. [ ]是个空数组

—— 隐式转换

答案:ACD

题解中还有其他宝藏信息,整理如下~ ヾ(•ω•`)o:

  1. 对于parseInt的考点(C选项的扩展),一位网友给出了其他常考的考点,放在第6点中
  1. 看下面一段代码:if ([]) { console.log(true); }
结果输出了true  
其实\[ \] == false,因为在等号比较时,如果有一边是Boolean值,会优先将左右两边的数据转为Number,`Number([]) == 0`,`Number(false)==0`,因此`[] == false`  
但进行if判断时,会将数据转为Boolean类型,`Boolean([])=true`,所以可以输出true
  1. 关于js中涉及的隐式类型转换,此处有一篇好文可以参考:here,从双等号的比较延申到.toString()方法和.valueOf()方法,很赞( •̀ ω •́ )✧
部分截图如下:  
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210613174957269.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNTIzNzI1,size_16,color_FFFFFF,t_70)
  1. 2==“2” 返回true(都转成了Number);2===“2"返回false,因为恒等号还要比较"数据类型”

4.2 Boolean类型转换


在这里插入图片描述

单选题:上述代码的输出结果为?

A. false false false false false

B. false true false false false

C. false false true test Boolean

D. 其他几项都不对

答友精彩解析:

1.当作为一个构造函数(带有运算符 new)调用时,Boolean() 将把它的参数转换成一个布尔值,并且返回一个包含该值的 Boolean 对象。

如果作为一个函数(不带有运算符 new)调用时,Boolean() 只将把它的参数转换成一个原始的布尔值,并且返回这个值——强制类型转换

2.如果省略 value 参数,或者设置为 0、-0、null、“”、false、undefined 或 NaN,则该对象设置为 false。否则设置为 true(即使 value 参数是字符串 “false”)

答案:A

上面讲的是Boolean()的转换,还有一个关于逻辑非的转换,在第4.5点的题里一起写

4.3 加号与减号


单选题:如下代码输出的结果是什么?

console.log( 1+ “2”+“2”);

console.log( 1+ +“2”+“2”);

console.log( “A”-“B”+“2”);

console.log( “A”-“B”+2);

A. 122 122 NaN NaN

B. 122 32 NaN NaN2

C. 122 32 NaN2 NaN

D. 122 32 NaN2 NaN2

答友精彩解析:

  • 数字和字符串相加,会将数字转为字符串,所以结果是字符串拼接,第一句输出"122"
  • +“2”,这里的一元运算符+,会将字符串转为数字,于是1+ +“2” = 1+2 = 3,再与后面的字符串合并,所以第二句输出”32“
  • 减号会将减号两边都先转化成数字,而Number(“A”)、Number(“B”)结果是NaN,减法操作中,只要有一方为NaN,结果都是NaN,因此第三句是NaN和"2"的拼接,结果为NaN2(第4.1点中提到,双等号其中一方为NaN,结果为false)
  • 根据前一句的解析,“A”-"B"结果为NaN,与数字2相加,结果还是NaN
   
—— 隐式转换  
   
答案:C

4.4 API强制类型转换


不定项选题:对于代码var a = 10.42; 取出a的整数部分,以下代码哪些是正确的?

A. parseInt( a );

B. Math.floor( a );

C. Math.ceil( a );

D. a.split(’.’)[0];

答友精彩解析:

A. parseInt转换为整数,默认为10进制,结果为10

B.floor向下取整,结果为10 —— floor是地板的意思,向下取整,辅助记忆

C.ceil向上取整,结果为11

D.split操作数必须是正则或字符串,结果为TypeError

答案:AB

4.5 new String 与 ’ ’


不定项选题:下面哪些执行结果为true()?

A. ‘foo’ == new function(){ return String(‘foo’); };

B. ‘foo’ == new function(){ return new String(‘foo’); };

C. [] == 0

D. ![]

E: !0

分析:

AB选项的分析可以看这两篇文章:文一文二

C.前面讲解双等号时也提到过,Number([])结果是0,因此C选项正确

D.一位牛友给出了一个很赞的解析,另一位牛友的提问帮助我们理解,概括如下:

  • 牛友观点:对象总等于真
  • 问:那为什么在控制台测试时,{} == true, {} === true得到的结果均为false呢?(以下截图是我模拟的,有误之处还请指正)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210617223846940.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNTIzNzI1,size_16,color_FFFFFF,t_70)
  • 答:因为双等号有一方为布尔值时,会先将两边都转为Number类型,所以,在控制台测试{} == true和 {} === true,实际上是测试{} == 1, {} === 1,所以结果才都是false。因此,如果你想要测试"对象总等于真",应该使用 !{} 和!!{}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210617223219274.png)  
对象是引用类型的值,引用地址是判断对象为不为真的依据,每一个对象都有自己的引用地址,因此每一个对象都必然为真,而不是{}的属性和属性值,没有属性和属性值只能说他是一个空对象,空对象和其他对象一样都有引用地址([原文地址]( ))

E.由于Boolean(0) == false,因此!0 = true;,E选项正确

答案:BCE

5.API使用

=======

5.1 map函数


let array = [,1,2,3];

array = array.map((i)=>++i);

A. [,2,,3,,4](为了看得清楚些,使用了中文的逗号,本应是英文半角的逗号)

B. [NaN, 2, NaN, 3, NaN,4]

C. [1,2,1,3,1,4]

D. [null, 2, null, 3, null, 4]

分析:

摘自这篇文章

ES5:

  • 在大多数情况下会忽略空位,例如forEach()、for in、filter()、every()、reduce()和some()都会跳过空位,
  • map()会跳过空位,但会保留这个值,join()和toString()会将空位与undefined以及null处理成空字符串

ES6则是将空位转为undefined:

  • 例如Array.form()方法会将数组的空位转为undefined
  • 扩展运算符也会将空位转为undefined,
  • copyWithin()会连同空位一起拷贝
  • for of循环也会遍历空位并将值作为undefined,
  • includes()、entries()、keys()、values()、find()和findIndex()等会将空位处理成undefined

答案:A

5.2 parseInt函数


第4点的那道题的题解中,有网友给出了parseInt函数的其他常考考点,此处截图出来:

在这里插入图片描述

其中提到的易考点:parseInt函数的第二个参数——数组的下标,经典题如下:

var arr = [1,2,3,2,5];

console.log(arr.map(parseInt));// [1, NaN, NaN, 2, NaN]

parseInt函数有三个参数,分别是:数组元素、该元素下标、数组本身

因此,这个过程其实是这样的:

arr.map( (i)=>parseInt(arr[i], i, arr) );

/*

计算过程如下,第三个参数是数组本身,此处省略不写:

parseInt(1,0) —— 十进制,1在0-9之间,输出1

parseInt(2,1) —— 进制小于2,返回NaN

parseInt(3,2) —— 二进制,但3不在0-1之间,输出NaN

parseInt(2,3) —— 三进制,2在0-2之间,输出2

parseInt(5,4) —— 四进制,5不在0-3之间,输出NaN

最终结果为:[1, NaN, NaN, 2, NaN]

*/

6. 立即执行函数

==========

单选题1:假设 output 是一个函数,输出一行文本。下面的语句输出结果是什么?

output(typeof (function() {output(“Hello World!”)})());

A. undefined Hello World!

B. Object

C. String

D. function

E. Hello World! undefined

题目给的代码看起来不太方便,于是我把它们放到编辑器里,帮助看清括号的归属。

typeof是可以不需要括号的,就像这样:

在这里插入图片描述

题目里紧挨着typeof的括号应该是用于构成后面的立即执行函数的,因此,我把代码的排版改成这样:

output( typeof

(

function() {

output(“Hello World!”)

}

)()

);

分析:

output是一个用于输出文本的的函数

  • 先执行立即执行函数,调用output函数,输出"Hello World!",
  • 然后output出这个立即执行函数的返回值,由于没有写return,默认会返回undefined,所以输出undefined

答案:E

7. ES5的变量提升

============

(function() {

var x=foo();

var foo=function foo() {

return “foobar”

};

return x;

})();

单选题1:上述代码执行结果为?

A. foo()

B. 类型错误

C. undefined

D. foobar

答友精彩解析:

  • 变量提升,但是函数表达式不会提升。
  • x在foo之前定义,此时foo是undefined。运行到x = foo();时,会报错TypeError: foo is not a function。
  • 如果把x定义放在foo的后面,就不会报错
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210617170613119.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNTIzNzI1,size_16,color_FFFFFF,t_70)  
变量提升之后,应该是这样的:  
var x;  
var foo;  
x = foo(); //此时的foo还只是undefined,不是函数  
foo = function foo(){};  
   
答案:B  
这里还有一篇好文:[here]( )

单选题2:写出下面代码的运行结果

var a,b;

(function(){

alert(a);

alert(b);

var a=b=3;

alert(a);

alert(b);

})();

alert(a);

alert(b);

A. undefined,undefined,3,3,undefined,3

B. undefined,undefined,3,3,undefined,undefined

C. 0,0,3,3,undefined,undefined

D. undefined,undefined,3,3,0,0

分析:立即执行函数里,变量a和b的声明会提升到函数最前头,所以,第一个alert出的a是函数里的局部变量a。整段代码经变量提升后,可以看作是这样的:

var a,b;

(function(){

var a;

alert(a); // 此处的a是局部变量a,未初始化,为undefined

alert(b); // 此处的b是全局变量b,未初始化,为undefined

a=b=3; // 全局b=3,局部a=3

alert(a); // 输出3

alert(b); // 输出3

})();

alert(a); // 全局a,为undefined

alert(b); // 全局b,为3

因此,答案选A

8.JS对象转基本类型

===========

不定项选题:以下哪些代码执行后i的值为10:

A. let i =1 + {

valueOf() { return 9; }

};

B. let i = 0;

new Array(10).forEach(() => {

i++;

});

C. let i = parseInt(‘0xA’);

D. let i = 5;

function a(i) {

i *= 2;

}

a(i);

分析:可以看这篇文章:here

A. 数字1和一个对象相加,会触发"对象–>基本类型"机制。

由于是加法运算,且该对象重写了ValueOf函数,根据文章描述,该对象会根据重写的ValueOf函数,转变成Number类型,也就是9;

式子就转变为let i = 1+ 9 = 10;,因此返回的是10

B.new Array(10)创建了数组但未初始化,里面都是empty,forEach不处理为空的数组元素,即不会执行回调函数,因此,B选项的结果 i 还是0

C.parseInt可以识别‘0x’,‘0x’代表十六进制,十六进制的A是10,因此C选项结果为10

D.向函数a传入基本数据类型的数据 i 作为形参,在a函数的作用域内改变了这个形参的值,但不会影响全局中的 i 本身,因为传的是值,相当于深拷贝(如果传入的是复杂数据类型的数据,才会影响全局变量,因为传的是引用,相当于浅拷贝)

在这里插入图片描述

关于"JS对象转为基本类型"这个知识点,还有一篇好文:here

答案:AC

9.W3C标准盒模型

==========

单选题1:在W3C标准盒模型中,默认情况下块元素的总宽度为?

A. content

B. content + 2 * padding

C. content + 2 * padding + 2 * border

D. content + 2 * padding + 2 * border + 2 * margin

答友精彩解析:

W3C标准盒子模型 = margin + border + padding + width (width = content)

IE盒子模型 = margin + width (width = border + padding + content)

这道题问的是元素的宽度,不是盒子的宽度

答案:A


单选题2:CSS盒子模型中()是透明的,这部分可以显示背景

A. border

B. margin

C. padding

D. content

分析:

CSS3中,新增了background-origin属性,

默认值是padding-box,代表从padding区域开始放置图片,其他区域平铺,本题考的应该是默认情况

如果background-origin值为content-box代表从content区域放置图片;

如果值为border-box代表从border区域就放置图片了

可以参考我的这篇文章

答案:C


单选题3:根据规范,以下 HTML 和 CSS 代码解析后, container.clientWidth的值是:

A. 200

B. 240

C. 280

D. 300

content

分析:官方给出的element.clientWidth是这样的:

内联元素以及没有 CSS 样式的元素的 clientWidth 属性值为 0。Element.clientWidth 属性表示元素的内部宽度,以像素计。该属性包括内边距 padding,但不包括边框 border、外边距 margin 和垂直滚动条(如果有的话)在这里插入图片描述

官网链接:here

因此,本题中的container.clientWidth = width + padding * 2 = 200 + 20 * 2 = 240

答案:B


单选题4:当margin-top、padding-top的值是百分比时,分别是如何计算的?

A. 相对父级元素的height,相对自身的height

B. 相对最近父级块级元素的height,相对自身的height

C. 相对父级元素的width,相对自身的width

D. 相对最近父级块级元素的width,相对最近父级块级元素的width

总结一下

面试前要精心做好准备,简历上写的知识点和原理都需要准备好,项目上多想想难点和亮点,这是面试时能和别人不一样的地方。

还有就是表现出自己的谦虚好学,以及对于未来持续进阶的规划,企业招人更偏爱稳定的人。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。

为了帮助大家更好更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。

前端面试题汇总

JavaScript

性能

linux

前端资料汇总

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值