最后
小编综合了阿里的面试题做了一份前端面试题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:
- 对于parseInt的考点(C选项的扩展),一位网友给出了其他常考的考点,放在第6点中
- 看下面一段代码:
if ([]) { console.log(true); }
结果输出了true
其实\[ \] == false,因为在等号比较时,如果有一边是Boolean值,会优先将左右两边的数据转为Number,`Number([]) == 0`,`Number(false)==0`,因此`[] == false`
但进行if判断时,会将数据转为Boolean类型,`Boolean([])=true`,所以可以输出true
- 关于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)
- 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
分析:
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
分析:官方给出的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
前端资料汇总
前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。