「2024」打算跳槽涨薪,必问面试题及答案 -- JavaScript 篇(1)

函数在被调用的时候会先进行预编译:

全局作用域预编译:

  • 创建上下文 GO 对象。

  • 找变量声明,将变量名作为 GO 对象的属性名,值为 undefined

  • 找函数式声明,将值赋予函数体

函数作用域预编译:

  • 创建上下文 AO 对象

  • 将形参和实参作为 AO 对象的属性,赋值为 undefined

  • 实参和形参相统一

  • 在函数体内找函数声明,将值赋予函数体。

相关面试题:

// 运行结果:

/*

function a(){}

12

function c(){}

undefined

undefined

function (){}

function c(){}

*/

5、null 和 undefined 的区别。


null 和 undefined 两个都表示无的值。

作者设计 js 的时候,借鉴的 java 语言先设计的 null 。null 使用的时候会被隐式转化成 0,不容易发现错误。

console.log( number(null) ) //0

undefined 是为了填补 null 的坑。所以后来又新增了 undefined 。

console.log( number(undefined) ) //NaN

6、new 操作符具体做了什么?


  • 创建了一个空对象。

  • 将空对象的原型指向于构造函数的原型。

  • 将空对象作为构造函数的上下文。

  • 对构造函数有返回值的处理判断。

实现 new 操作符的方法:

function create( fn,…args ){

var obj={}

Object.setPrototypeOf( obj,fn.prototype )

var resault = fn.apply(obj,args)

return (resault instanceof Object) ? result : obj

}

7、为什么会有闭包?它解决了什么问题?


7.1、什么是闭包?

闭包就是函数嵌套函数,通过函数内的函数访问变量的规则,实现外部访问函数内的变量。

7.2、闭包的特点:

  • 函数嵌套函数。

  • 函数内部可以引用函数外部的参数和变量。

  • 参数和变量不会被垃圾回收机制回收。

实例3:闭包解决问题

var liArr = document.getElementsByTagName(‘li’)

for(var i=0;i<liArr.length;i++){

(function(i){

liArr[i].onclick = function(){

console.log(‘点击元素’,liArr[i])

}

})(i)

}

7.3、闭包优点:

  • 保护变量安全,实现封装,防止变量声明冲突和全局污染。

  • 在内存当中维持一个变量,可以做缓存。

  • 匿名函数自执行函数可以减少内存消耗。

防抖和节流就是闭包的经典应用。

7.4、闭包缺点:

  • 变量会驻留在内存中,造成内存损耗问题。解决办法:把闭包函数设置为 null 。

  • 内存泄漏

8、防抖和节流,你了解多少?


8.1、什么是防抖函数?

当持续触发事件,一定时间内没有再触发事件,事件处理函数才会执行一次,如果在设定的时间到来之前又触发了事件,就会重新计时。

防抖函数常见的实际应用:使用 echart 的时候,浏览器 resize 时,需要重新绘制图表大小,还有典型的输入框搜索应用。

8.2、节流函数是什么?

当持续触发事件的时候,保证一段时间内只调用一次事件处理函数,一段时间内,只允许做一件事情。

防抖和节流主要是用来限制触发频率较高的事件,再不影响效果的前提条件下,降低事件触发频率,减小浏览器或服务器的压力,提升用户体验效果。

9、数组去重有几种方法?


方法1: new set()

return Array.from(new Set(arr))

// 或

return […new Set(arr)]

方法2:使用两次循环

for(var i=0,len=arr.length;i<len;i++){

for(var j=i+1,len=arr.length;j<len;j++){

if( arr[i]===arr[j] ){

arr.splice(i,1)

j–;

len–

}

}

}

return arr

方法3:indexOf 实现

let arr1 = []

for(var i=0;i<arr.length;i++){

if( arr1.indexOf(arr[i]) === -1 ){

arr1.push(arr[i])

}

}

return arr1

方法4:includes 实现

let arr1 = []

for(var i=0;i<arr.length;i++){

if( !arr1.includes(arr[i]) ){

arr1.push(arr[i])

}

}

return arr1

方法5:filter 实现

array.indexOf(item,start) start 表示开始检索的位置。

return arr.filter(( item, index )=>{

return arr.indexOf( item, 0 ) == index

})

10、call、bind 和 apply 的区别


三者都是改变函数执行的上下文,即改变 this 指向。

它们之间的区别为:

  • call 和 apply 会立即执行,bind 返回的是一个函数,需调用后执行。

  • 第二参数是传入要执行的方法中的参数,call 和 bind 是独立传递参数,apply 是以数组传递参数的

使用场景:

1、需要改变某个函数的this指向时

2、当参数较少时可以使用call,参数较多可以使用apply以数组的方式传递

3、当需要重复调用时,可以使用bind新定义一个方法

11、js 判断变量是不是数组,你能写出几种方法?


方法1:isArray

var arr = [1,2,3]

console.log(Array.isArray(arr))

方法2:instanceof

var arr = [1,2,3]

console.log( arr instanceof Array )

console.log( arr instanceof Object )

该方法不够严谨。

方法3:prototype

console.log( Object.prototype.toString.call(arr).indexOf(‘Array’)>-1 )

方法4:isPrototypeOf

console.log( Array.prototype.isPrototypeOf( arr ) )

方法5:constructor

console.log(arr.constructor.toString().indexOf(‘Array’)>-1 )

12、slice 是干嘛的? splice 是否会改变原数组?


slice 是用来截取字符串的,返回一个新数组,但不会影响原数组。

使用语法:

arr.slice( start , end )

截取 arr 数组,从 start 开始到 end 结束,第二个参数是可选参数,没有时从 start 开始截取到结尾。

如果 start 参数是负数时,就会从 arr.lengtn + start 开始截取到结束。

var arr = [‘a’,‘b’,‘c’,‘d’,‘e’]

console.log( arr.slice(-3) ) // [“c”, “d”, “e”]

console.log(arr) //[“a”, “b”, “c”, “d”, “e”]

splice 是一个更强大的方法,可以添加、删除、替换数组元素,返回的是被删除元素,它的操作会改变原数组。

使用语法:

splice( start, n, new )

从 start 开始,删除 n 个元素,然后把 new 添加到 start 元素之后。第三个参数为可选参数

  • n 为 0 且第三个参数不为空时,表示添加新元素到 start 之后。

  • n 不为 0 且第三个参数不为空时,表示把 start 之后的 n 个元素替换成 new 。

  • n 不为 0 且第三个参数为空时,表示删除 start 后的 n 个元素。

var arr = [‘a’,‘b’,‘c’,‘d’,‘e’]

var ar = arr.splice( 1, 1 ,‘f’,‘g’)

console.log(‘ar’,ar) // [“b”]

console.log(‘arr’,arr) // [“a”, “f”, “g”, “c”, “d”, “e”]

13、== 和 === 有什么不同?


== 比较的是值,=== 除了比较值,还比较类型。

console.log( [1,2]==‘1,2’ ) // true

console.log( [1,2] === ‘1,2’ ) //false

valueOf 方法返回 Math 对象的原始值,通常由 javascript 在后台自动调用,并不显示的出现在代码中。

console.log([1,2].valueOf()) //[1,2]

console.log(‘1,2’.valueOf()) //[1,2]

// 所以

console.log( [1,2]==‘1,2’ ) // true

不管是字符串和数字比较,还是布尔值和数字比较,都会使用 valueOf 隐式转换。

总结:== 需要使用 valueOf() 进行隐式转换,所以性能差。 === 会避开一些不必要的麻烦。

14、this 的指向


大厂笔试题:

var name = ‘window name’

var p1 = {

name:‘p1 name’,

showName:function(){

console.info(this.name)

}

}

var fn = p1.showName

fn()

p1.showName()

var p2 = {

name:‘p2 name’,

showName:function(fun){

fun()

}

}

p2.showName(p1.showName)

p2.showName = p1.showName

p2.showName()

/*

运行结果:

window name

p1 name

window name

p2 name

*/

这是一道关于 this 指向的面试题,接下来我们就说说 this 是如何指向的?

this 对象是运行时基于函数的执行环境绑定的:

  • 在全局函数中,this 等于 window 。

  • 函数上下文调用,严格模式下 this 为 undefined ,非严格模式下,this 指向 window 。

  • 当函数被作为某个对象的方法被调用时,this 等于那个对象。如果使用 call apply 改变当前 this 时,将会指向为传递过来的那个 this 。

  • 匿名函数的执行环境具有全局性,因此 this 指向 window。

  • 构造函数内的 this 指向创建的实例对象。

  • dom 事件处理函数,this 指向触发该事件的元素。

  • setTimeout 和 setInterval 中的 this 指向全局变量 window

15、js 中的继承有哪些方式呢?


第 1 种:原型链继承

function Parent(){

this.name = “前端人”

}

Parent.prototype.showName = function(){

console.log(this.name)

}

function Child(){}

//原型链继承

Child.prototype = new Parent()

var p = new Child()

console.dir(p.name) //前端人

特点:

  • 实例的是子类的实例,也是父类的实例。

  • 父类新增原型方法和属性,子类都能访问到。

  • 简单,方便实现

第 2 种:借用构造函数

function Animal (name) {

this.name = name || ‘Animal’;

this.sleep = function(){

console.log(this.name + ‘正在睡觉!’);

}

}

Animal.prototype.eat = function(food) {

console.log(this.name + ‘正在吃:’ + food);

};

function Cat(name){

Animal.call(this);

this.name = name || ‘Tom’;

}

// Test Code

var cat = new Cat();

console.log(cat.name);

console.log(cat.sleep());

console.log(cat instanceof Animal); // false

console.log(cat instanceof Cat); // true

特点:

  • 创建子类时,可以向父类传递参数。

  • 可以实现多继承,call 多个父类对象。

  • 解决方法1中,子类实例共享父类引用属性的问题。

还有组合式继承、ES6 的继承 和 寄生组合继承等等。每种继承方式都有各自的特点和缺点。

16、严格模式与非严格模式的区别,你了解多少?


JavaScript 语言是一门弱类型语言,存在许多类型错误,因此 ES6 引入了严格模式概念。

如果不加 ‘use strict’ 常规模式下就是属于非严格模式。

严格模式

在 js 文件顶部添加 ‘use strict’ 就属于严格模式,严格模式也可以指定在函数内部。

严格模式,是为 js 定义来了一种不同的解析与执行模型,在严格模式下,ECMAScipt 3 中一些不解和不确定的行为将得到处理,而且会对不安全的操作会抛出异常。‘use strict’ 会告诉浏览器引擎可以切换到严格模式执行。

严格模式与非严格模式区别

严格模式

非严格模式

变量必须声明才能赋值

变量不进行声明,可直接赋值

不能使用 delete 字符删除变量或对象

可以使用 delete 删除

函数参数变量名不允许重复

变量名重复,获取最后最后那个值

普通函数内的 this 为 undefined

普通函数内的 this 为 window

不允许使用八进制

允许任意进制

eval 和 arguments 当做关键字,不能被赋值和用作变量名

可以使用 eval 、arguments 作为变量名

call、apply 传入 null undefined 保持原样不被转为window

默认转为 window 对象

限制对调用栈的检测能力,访问 arguments.callee 会抛出异常

arguments.callee 运行正常

17、隐式转化相关面试题


console.log( ‘2’>10 ) //false

console.log( ‘2’>‘10’ ) //true

console.log( ‘abc’>‘b’ ) //false

console.log( ‘abc’>‘aab’ ) //true
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后的最后

面试题千万不要死记,一定要自己理解,用自己的方式表达出来,在这里预祝各位成功拿下自己心仪的offer。
需要完整面试题的朋友可以点击蓝色字体免费获取

大厂面试题

面试题目录

true
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-9yKLKeHX-1712246453518)]

[外链图片转存中…(img-LGF833HR-1712246453519)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

[外链图片转存中…(img-0lmV57BB-1712246453519)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后的最后

面试题千万不要死记,一定要自己理解,用自己的方式表达出来,在这里预祝各位成功拿下自己心仪的offer。
需要完整面试题的朋友可以点击蓝色字体免费获取

[外链图片转存中…(img-UxqHkLes-1712246453520)]

[外链图片转存中…(img-d4yufjgn-1712246453520)]

[外链图片转存中…(img-Zi7vcezj-1712246453520)]

[外链图片转存中…(img-nP0tgGhK-1712246453520)]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值