JavaScript面试经,offer拿到手软

2023-11-22 20:36

本文主要是介绍JavaScript面试经,offer拿到手软,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章来源于公众号:猴哥说前端 作者:monkeysoft

本文给大家分享一些 JavaScript 面试经验,在这金九银十的招聘季,希望大家都能找到满意的工作。

JavaScript的数据类型都有什么?

基本数据类型:String,Boolean,Number,Undefined,Null

引用数据类型:Object(Array,Date,RegExp,Function)

javascript中=====的区别是什么?

==会自动进行类型转换,===不会

例举3种强制类型转换和2种隐式类型转换?

强制(parseInt,parseFloat,Number())

隐式(==) 1==”1”//true

null==undefined//true

原生 JS 中 call()、apply()、bind() 方法有什么区别?

三个方法都可以改变函数运行时的 this 指向。

三个方法第一个参数都是函数调用执行时this 指向的对象。

call() 方法第二个参数是个可变参数,是函数调用执行时本身所需要的参数。

apply() 方法第二个参数是数组或arguments。call()与apply()都是立即调用函数执行,在运行时修改this指向。

bind()是返回一个新的函数,新函数的函数主体与原函数的函数主体一致,当新函数被调用时,函数体中 this 指向的是 bind() 方法第一个参数传递的对象,而bind() 方法不会影响原函数本身的 this 指向。

什么是闭包?特点是?

闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

闭包的特点:

(1)作为一个函数变量的一个引用,当函数返回时,其处于激活状态。

(2) 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。

简单的说,JavaScript 允许使用内部函数---即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。

事件委托是什么?

符合W3C标准的事件绑定 addEventLisntener /attachEvent

让利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执行!

如何阻止事件冒泡和默认事件

e. stopPropagation();//标准浏览器

event.canceBubble=true;//ie9之前

阻止默认事件:

为了不让a点击之后跳转,我们就要给他的点击事件进行阻止

return false

e.preventDefault();

document load 和document ready的区别?

Document.onload 是在结构和样式加载完才执行js

window.onload:不仅仅要在结构和样式加载完,还要执行完所有的样式、图片这些资源文件,全部加载完才会触发window.onload事件

Document.ready原生种没有这个方法,jquery中有 $().ready(function)

为了保证页面输出安全,我们经常需要对一些特殊的字符进行转义,请写一个函数escapeHtml,将, &, “进行转义

return str.replace(/[”&]/g, function(match) {switch (match) {case “”:return “>”;case “&”:return “&”;case “\””:return “"”;}});
}

简述创建函数的几种方式

第一种(函数声明):function sum1(num1,num2){ return num1+num2; }

第二种(函数表达式):var sum2 = function(num1,num2){ return num1+num2; }

第三种(函数对象方式):var sum3 = new Function("num1","num2","return num1+num2");

把 Script 标签 放在页面的最底部的body封闭之前 和封闭之后有什么区别?浏览器会如何解析它们?

如果说放在body的封闭之前,将会阻塞其他资源的加载

如果放在body封闭之后,不会影响body内元素的加载

iframe的优缺点?

优点:

  1. 解决加载缓慢的第三方内容如图标和广告等的加载问题
  2. Security sandbox
  3. 并行加载脚本

缺点:

  1. iframe会阻塞主页面的Onload事件
  2. 即时内容为空,加载也需要时间
  3. 没有语意

Javascript如何实现继承?

原型链继承,借用构造函数继承,组合继承,寄生式继承,寄生组合继承

请你谈谈Cookie的弊端?

缺点:

1.Cookie 数量和长度的限制。部分浏览器每个 domain 最多只能有50条 cookie,基本所有浏览器中每个 cookie 长度不能超过4KB,否则会被截掉。

2.安全性问题。如果 cookie 被人拦截了,那人就可以取得所有的 session 信息。即使加密也与事无补,因为拦截者并不需要知道 cookie 的意义,他只要原样转发 cookie 就可以达到目的了。

3.有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。

4.占用网络上传带宽。每次请求服务器资源时,都会携带 cookie 信息向服务器传递。

DOM操作——怎样添加、移除、移动、复制、创建和查找节点?

创建新节点

  • createDocumentFragment() // 创建一个DOM片段
  • createElement() // 创建一个具体的元素
  • createTextNode() // 创建一个文本节点

添加、移除、替换、插入

  • appendChild()
  • removeChild()
  • replaceChild()
  • insertBefore() // 在已有的子节点前插入一个新的子节点

查找

  • getElementsByTagName() // 通过标签名称
  • getElementsByName() // 通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的)
  • getElementById() // 通过元素Id,唯一性

js延迟加载的方式有哪些?

  1. defer和async
  2. 动态创建DOM方式(创建script,插入到DOM中,加载完毕后callBack)
  3. 按需异步载入js

documen.write和 innerHTML 的区别?

document.write 只能重绘整个页面

innerHTML 可以重绘页面的一部分

哪些操作会造成内存泄漏?

内存泄漏指任何对象在您不再拥有或需要它之后仍然存在。垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收。

  1. setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏。
  2. 闭包
  3. 控制台日志
  4. 循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)

判断一个字符串中出现次数最多的字符,统计这个次数?

var str = 'asdfssaaasasasasaa';
var json = {};
for (var i = 0; i < str.length; i++) {if(!json[str.charAt(i)]){json[str.charAt(i)] = 1;}else{json[str.charAt(i)]++;}
};
var iMax = 0;
var iIndex = '';
for(var i in json){if(json[i]>iMax){iMax = json[i];iIndex = i;}
}
alert('出现次数最多的是:'+iIndex+'出现'+iMax+'次');

数组扁平化

数组扁平化是指将一个多维数组变为一个一维数组

const arr = [1, [2, [3, [4, 5]]], 6];
// => [1, 2, 3, 4, 5, 6]

方法一:使用flat()

const res1 = arr.flat(Infinity);

方法二:利用正则

const res2 = JSON.stringify(arr).replace(/\[|\]/g, '').split(',');

但数据类型都会变为字符串

方法三:正则改良版本

const res3 = JSON.parse('[' + JSON.stringify(arr).replace(/\[|\]/g, '') + ']');

方法四:使用reduce

const flatten = arr => {return arr.reduce((pre, cur) => {return pre.concat(Array.isArray(cur) ? flatten(cur) : cur);}, [])
}
const res4 = flatten(arr);

方法五:函数递归

const res5 = [];
const fn = arr => {for (let i = 0; i < arr.length; i++) {if (Array.isArray(arr[i])) {fn(arr[i]);} else {res5.push(arr[i]);}}
}
fn(arr);

数组去重

const arr = [1, 1, '1', 17, true, true, false, false, 'true', 'a', {}, {}];
// => [1, '1', 17, true, false, 'true', 'a', {}, {}]

方法一:利用Set

const res1 = Array.from(new Set(arr));

方法二:两层for循环+splice

const unique1 = arr => {let len = arr.length;for (let i = 0; i < len; i++) {for (let j = i + 1; j < len; j++) {if (arr[i] === arr[j]) {arr.splice(j, 1);// 每删除一个树,j--保证j的值经过自加后不变。同时,len--,减少循环次数提升性能len--;j--;}}}return arr;
}

方法三:利用indexOf

const unique2 = arr => {const res = [];for (let i = 0; i < arr.length; i++) {if (res.indexOf(arr[i]) === -1) res.push(arr[i]);}return res;
}

方法四:利用include

const unique3 = arr => {const res = [];for (let i = 0; i < arr.length; i++) {if (!res.includes(arr[i])) res.push(arr[i]);}return res;
}

方法五:利用filter

const unique4 = arr => {return arr.filter((item, index) => {return arr.indexOf(item) === index;});
}

方法六:利用Map

const unique5 = arr => {const map = new Map();const res = [];for (let i = 0; i < arr.length; i++) {if (!map.has(arr[i])) {map.set(arr[i], true)res.push(arr[i]);}}return res;
}

类数组转化为数组

类数组是具有length属性,但不具有数组原型上的方法。常见的类数组有arguments、DOM操作方法返回的结果。

方法一:Array.from

Array.from(document.querySelectorAll('div'))

方法二:Array.prototype.slice.call()

Array.prototype.slice.call(document.querySelectorAll('div'))

方法三:扩展运算符

[...document.querySelectorAll('div')]

方法四:利用concat

Array.prototype.concat.apply([], document.querySelectorAll('div'));

debounce(防抖)

触发高频时间后n秒内函数只会执行一次,如果n秒内高频时间再次触发,则重新计算时间。

const debounce = (fn, time) => {let timeout = null;return function() {clearTimeout(timeout)timeout = setTimeout(() => {fn.apply(this, arguments);}, time);}
};

防抖常应用于用户进行搜索输入节约请求资源,window触发resize事件时进行防抖只触发一次。

throttle(节流)

高频时间触发,但n秒内只会执行一次,所以节流会稀释函数的执行频率。

const throttle = (fn, time) => {let flag = true;return function() {if (!flag) return;flag = false;setTimeout(() => {fn.apply(this, arguments);flag = true;}, time);}
}

节流常应用于鼠标不断点击触发、监听滚动事件。

函数珂里化

指的是将一个接受多个参数的函数 变为 接受一个参数返回一个函数的固定形式,这样便于再次调用,例如f(1)(2)

经典面试题:实现add(1)(2)(3)(4)=10; 、 add(1)(1,2,3)(2)=9;

function add() {const _args = [...arguments];function fn() {_args.push(...arguments);return fn;}fn.toString = function() {return _args.reduce((sum, cur) => sum + cur);}return fn;
}

深拷贝

递归的完整版本(考虑到了Symbol属性):

const cloneDeep1 = (target, hash = new WeakMap()) => {// 对于传入参数处理if (typeof target !== 'object' || target === null) {return target;}// 哈希表中存在直接返回if (hash.has(target)) return hash.get(target);const cloneTarget = Array.isArray(target) ? [] : {};hash.set(target, cloneTarget);// 针对Symbol属性const symKeys = Object.getOwnPropertySymbols(target);if (symKeys.length) {symKeys.forEach(symKey => {if (typeof target[symKey] === 'object' && target[symKey] !== null) {cloneTarget[symKey] = cloneDeep1(target[symKey]);} else {cloneTarget[symKey] = target[symKey];}})}for (const i in target) {if (Object.prototype.hasOwnProperty.call(target, i)) {cloneTarget[i] =typeof target[i] === 'object' && target[i] !== null? cloneDeep1(target[i], hash): target[i];}}return cloneTarget;
}

这篇关于JavaScript面试经,offer拿到手软的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/412750

相关文章

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

破茧 JDBC:MyBatis 在 Spring Boot 中的轻量实践指南

《破茧JDBC:MyBatis在SpringBoot中的轻量实践指南》MyBatis是持久层框架,简化JDBC开发,通过接口+XML/注解实现数据访问,动态代理生成实现类,支持增删改查及参数... 目录一、什么是 MyBATis二、 MyBatis 入门2.1、创建项目2.2、配置数据库连接字符串2.3、入

Springboot项目启动失败提示找不到dao类的解决

《Springboot项目启动失败提示找不到dao类的解决》SpringBoot启动失败,因ProductServiceImpl未正确注入ProductDao,原因:Dao未注册为Bean,解决:在启... 目录错误描述原因解决方法总结***************************APPLICA编

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

Apache Ignite 与 Spring Boot 集成详细指南

《ApacheIgnite与SpringBoot集成详细指南》ApacheIgnite官方指南详解如何通过SpringBootStarter扩展实现自动配置,支持厚/轻客户端模式,简化Ign... 目录 一、背景:为什么需要这个集成? 二、两种集成方式(对应两种客户端模型) 三、方式一:自动配置 Thick

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

Java.lang.InterruptedException被中止异常的原因及解决方案

《Java.lang.InterruptedException被中止异常的原因及解决方案》Java.lang.InterruptedException是线程被中断时抛出的异常,用于协作停止执行,常见于... 目录报错问题报错原因解决方法Java.lang.InterruptedException 是 Jav