目录
1、Promsie.all() 使用过吗, 它是怎么使用的 ?
2、for in 和 for of 循环的区别 ?
3、 什么是事件流以及事件流的传播机制 ?
4、token 一般存放在哪里 ? 为什么不存放在 cookie 内 ?
5、 数组方法 forEach 和 map 的区别 ?
6、 ES6 中 Set 和 Map 的区别 ?
7、 0.1 + 0.2 为什么不等于 0.3, 在项目中遇到要怎么处理 ?
8、 什么是模块化思想 ?
9、 说说怎么用js 写无缝轮播图
10、 闭包的使用场景 ?
10.1 防抖:
10.2 节流:
10.3 迭代器:
10.4 缓存:
10.5 getter和setter:
10.6 函数的柯里化:
10.7 循环中绑定事件或执行异步代码:
10.8 单例模式:
🌻 promise.all()用于一个异步操作需要在几个异步操作完成后再进行时使用。 🌻 promise.all()接受一个 promise 对象组成的数组参数,返回 promise 对象。 🌻 当数组中所有promise 都完成了,就执行当前 promise 对象的 then 方法,如果数组中有一个 promise 执行失败了,就执行当前promise 对象的 catch 方法。2、for in 和 for of 循环的区别 ?
`for in` 用于遍历对象的键 ( `key` ) , `for in` 会遍历所有自身的和原型链上的可枚举属性。如果是数组,for in 会将数组的索引 (index) 当做对象的 key 来遍历,其他的 object 也是一样的。
`for of` 是 `es6` 引入的语法,用于遍历 所有迭代器 iterator ,其中包括 `HTMLCollection` , `NodeList` , `Array` , `Map` , `Set` , `String` , `TypedArray` , `arguments` 等 对象的值 ( `item` )3、 什么是事件流以及事件流的传播机制 ?
事件触发后,从开始找目标元素,然后执行目标元素的事件,再到离开目标元素的整个过程称之为事件流。 W3C 标准浏览器事件流的传播分为 3 个阶段:捕获阶段、目标阶段、冒泡阶段 🌻 捕获阶段指找目标元素的过程,这个找的过程,是从大的document 对象到 html ,再到body,......直到目标元素。 🌻 找到目标元素后,调用执行他绑定事件时对应的处理函数,这个过程被称之为目标阶段。 🌻 当目标元素的事件执行结束后,再从目标元素,到他的父元素。。。body 、 html 再到 document 的过程,是冒泡阶段。4、token 一般存放在哪里 ? 为什么不存放在 cookie 内 ?
🌻 token一般放在本地存储中。 token 的存在本身只关心请求的安全性,而不关心 token 本身的安全,因为 token 是服务器端生成的,可以理解为一种加密技术。但如果存在cookie 内的话,浏览器的请求默认会自动在请求头中携带cookie,所以容易受到 csrf 攻击。5、 数组方法 forEach 和 map 的区别 ?
🌻 forEach和 map 都是循环遍历数组中的每一项。 forEach() 和 map() 里面每一次执行匿名函数都支持 3 个参数:数组中的当前项item, 当前项的索引 index, 原始数组 input 。匿名函数中的 this 都是指 Window 。只能遍历数组。 🌻 他们的区别是:forEach 没有返回值,但 map 中要有返回值,返回处理后的所有新元素组成的数组。6、 ES6 中 Set 和 Map 的区别 ?
🌻 Set 是无重复值的有序列表。根据 `Object.is()` 方法来判断其中的值不相等,以保证无重复。 Set 会自动移除重复的值,因此你可以使用它来过滤数组中的重复值并返回结果。 Set 并不是数组的子类型,所以你无法随机访问其中的值。但你可以使用`has()` 方法来判断某个值是否存在于 Set 中,或通过 `size` 属性来查看其中有多少个值。 Set 类型还拥有 `forEach()` 方法,用于处理每个值 🌻 Map 是有序的键值对,其中的键允许是任何类型。与 Set 相似,通过调用 `Object.is()` 方法来判断重复的键,这意味着能将数值 5 与字符串 "5" 作为两个相对独立的键。使用 `set()` 方法能将任何类型的值关联到某个键上,并且该值此后能用 `get()` 方法提取出来。 Map 也拥有一个 `size` 属性与一个 `forEach()` 方法,让项目访问更容易7、 0.1 + 0.2 为什么不等于 0.3, 在项目中遇到要怎么处理 ?
🌻 计算机内部存储数据使用2 进制存储,两个数字进行的数学运算,首先是将这两个数字以 2 进制形式,存储在计算机内部,然后在计算机内部使用两个2 进制数字进行计算,最后将计算结果的 2 进制数字转为 10 进制展示出来。 🌻 由于10 进制的小数在转 2 进制的时候,规则是小数部分乘以 2 ,判断是否得到一个整数,如果得到整数,转换完成;如果没有得到整数,则继续乘以2 判断。所以, 0.1 和 0.2 在转换 2 进制的时候,其实是一个无限死循环,也就是一直乘以2没有得到整数的时候,但计算机内部对于无线死循环的数据,会根据一个标准保留 52 位。也就是说,计算机内部在存储0.1 和 0.2 的时候,本来就不精准,两个不精准的小数在计算后,距离精准的结果是有一定误差的。 🌻 项目中碰到这种情况,有3 种处理方法:
🍀 将小数乘以10的倍数,转为整数,然后计算,计算完成后,再缩小10的倍数,例如:
var result = ((0.1 * 10) + (0.2 * 10)) / 10
// result === 0.3
🍀
使用数字的toFixed
方法,强制保留小数点后多少位,例:
var result = (0.1 + 0.2).toFixed(2)
// result === 0.30
🍀
自定义数字运算方法,当需要进行数学运算的时候,不直接进行,调用自定义的方法进行,例: (加法封装)
function add(...args){
var num = args.find(item =>{
if(item != 0 && !item){
throw new Error("数学运算要使用数字")
}
})
var arr = args.map(item =>{
var index = (item+'').indexOf('.')
if(index >= 0){
return (item+'').split('.')[1].length
}
})
arr = arr.filter(item =>item)
if(arr.length){
var max = Math.max(...arr)
var data = args.map(item =>item * Math.pow(10, max))
var data.reduce((a, b) =>a + b) / Math.pow(10, max)
}else{
var data = args
return data.reduce((a, b) =>a + b)
}
}
// 调用使用:
var num1 = add(0.1, 0.2)
console.log(num1); // 0.3
var num2 = add(1, 2)
console.log(num2); // 3
var num3 = add(1, 2.1)
console.log(num3); // 3.1
8、 什么是模块化思想 ? 🌻 就是JS 中将不同功能的代码封装在不同的文件中 , 再互相引用时不会发生命名冲突的一种思想 , 大多数情况下 , 一个文件就是一个模块 🌻 模块化的实现,有多种方案:
🍀 CommonJS:
CommonJS 是 nodejs 中使用的模块化规范
在 nodejs 应用中每个文件就是一个模块,拥有自己的作用域,文件中的变量、函数都是私有的,与其他文件相隔离。模块导出: module.exports=数据 ,模块导入: require('模块文件路径')
🍀 ES6的模块化:
模块功能主要由两个命令构成: export 和 import 。 export 命令用于规定模块的对外接口, import 命令用于输入其他模块提供的功能。 一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取 模块内部的某个变量,就必须使用 export 关键字输出该变量。下面是一个 JS 文件,里面使用 export 命令输出变量。🍀 AMD (Asynchronous Module Definition):
特点 : 提倡依赖前置,在定义模块的时候就要声明其依赖的模块:导入模块 require([module],callback) ; 定义模块: define(' 模块名称 ', 函数 ) 。🍀 CMD (Common Module Definition):
CMD 规范是国内 SeaJS 的推广过程中产生的。提倡就近依赖(按需加载),在用到某个模块的时候 再去 require 。定义模块: define(function (require, exports, module) {}) ,使用模块: seajs.use() 9、 说说怎么用js 写无缝轮播图🌻 将所有需要轮播的内容动态复制一份,放在原本的容器中,加定时器让整个容器中的内容滚动轮播,当内容轮播到left值为原本的内容宽度时,快速将内容切换到 left 值为 0 的状态。10、 闭包的使用场景 ?
🌻 一个函数被当作值返回时,也就相当于返回了一个通道,这个通道可以访问这个函数词法作用域中的变量,即函数所需要的数据结构保存了下来,数据结构中的值在外层函数执行时创建,外层函数执行完毕时理因销毁,但由于内部函数作为值返回出去,这些值得以保存下来。而且无法直接访问,必须通过返回的函数。这也就是私有性。 🌻 本来执行过程和词法作用域是封闭的,这种返回的函数就好比是一个虫洞,开了挂。 🌻 闭包的形成很简单,在执行过程完毕后,返回函数,或者将函数得以保留下来,即形成闭包。10.1 防抖:
function debounce(fn, interval) {
let timer = null; // 定时器
return function() {
// 清除上一次的定时器
clearTimeout(timer);
// 拿到当前的函数作用域
let _this = this;
// 拿到当前函数的参数数组
let args = Array.prototype.slice.call(arguments, 0);
// 开启倒计时定时器
timer = setTimeout(function() {
// 通过apply传递当前函数this,以及参数
fn.apply(_this, args);
// 默认300ms执行
}, interval || 300)
}
}
10.2 节流:function throttle(fn, interval) {
let timer = null; // 定时器
let firstTime = true; // 判断是否是第一次执行
// 利用闭包
return function() {
// 拿到函数的参数数组
let args = Array.prototype.slice.call(arguments, 0);
// 拿到当前的函数作用域
let _this = this;
// 如果是第一次执行的话,需要立即执行该函数
if(firstTime) {
// 通过apply,绑定当前函数的作用域以及传递参数
fn.apply(_this, args);
// 修改标识为null,释放内存
firstTime = null;
}
// 如果当前有正在等待执行的函数则直接返回
if(timer) return;
// 开启一个倒计时定时器
timer = setTimeout(function() {
// 通过apply,绑定当前函数的作用域以及传递参数
fn.apply(_this, args);
// 清除之前的定时器
timer = null;
// 默认300ms执行一次
}, interval || 300)
}
}
10.3 迭代器:var arr =['aa','bb','cc'];
function incre(arr){
var i=0;
return function(){
//这个函数每次被执行都返回数组arr中 i下标对应的元素
return arr[i++] || '数组值已经遍历完';
}
}
var next = incre(arr);
console.log(next());//aa
console.log(next());//bb
console.log(next());//cc
console.log(next());//数组值已经遍历完
10.4 缓存:var fn=(function(){
var cache={};//缓存对象
var calc=function(arr){//计算函数
var sum=0;
//求和
for(var i=0;i
10.5 getter和setter:function fn(){
var name='hello'
setName=function(n){
name = n;
}
getName=function(){
return name;
}
//将setName,getName作为对象的属性返回
return {
setName:setName,
getName:getName
}
}
var fn1 = fn();//返回对象,属性setName和getName是两个函数
console.log(fn1.getName());//getter
fn1.setName('world');//setter修改闭包里面的name
console.log(fn1.getName());//getter
10.6 函数的柯里化:function curryingCheck(reg) {
return function(txt) {
return reg.test(txt)
}
}
var hasNumber = curryingCheck(/\d+/g)
var hasLetter = curryingCheck(/[a-z]+/g)
hasNumber('test1') // true
hasNumber('testtest') // false
hasLetter('21212') // false
10.7 循环中绑定事件或执行异步代码:var p1 = "ss";
var p2 = "jj";
function testSetTime(para1,para2){
return (function(){
console.log(para1 + "-" + para2);
})
}
var test = testSetTime(p1, p2);
setTimeout(test, 1000);
setTimeout(function(){
console.log(p1 + "-" + p2)
},1000)
10.8 单例模式:var Singleton = (function () {
var instance;
function createInstance() {
return new Object("I am the instance");
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
网页题目:前端面试题集锦(5)-创新互联
当前URL:https://www.cdcxhl.com/article20/dpgcco.html
成都网站建设公司_创新互联,为您提供响应式网站、网页设计公司、小程序开发、定制网站、用户体验、建站公司
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联