闭包

闭包就是有权访问其他函数内部变量的函数,或者子函数在外调用,子函数所在的父函数的作用域不会被释放。

const fn=()=>{let count=0;return function(){return count++;}
}
let c=fn();
console.log(c());//0
console.log(c());//1

防抖与节流

  • 防抖

不让频繁执行

function debounce(fn,space)
{let task=null;return function(){//先开启一个定时任务,当再次调用的时候,若定时任务还在存在就清空if(task){clearTimeOut(task);}task=setTimeOut(fn.apply(this,arguments),space);}
}
  • 节流

可以频繁执行,但是实在一定间隔内频繁执行

function trottle(fn,space)
{let task=null;return function(){if(!task){task=setTimeOut(()=>{task=null;fn.apply(this,arguments);},space)}}
}

call apply bind

  • bind(this or obj) 返回的是一个函数必须要调用
  • apply(this,[arguments])
  • call(this,…arguments)

原型链

  • 显示原型prototype

所有的函数包括构造函数都有一个prototype属性,这叫显示原型,是一个对象
记住只有构造函数才有prototype属性就对了

  • 隐式原型__proto__

所有的对象,数组或者函数都有一个__proto__属性,叫隐式原型,也是对象
记住只有对象才有__proto__属性就对了

  • 显示原型和隐式原型相等 Function.ptoto==Function.prototype
对象.__proto__=Constructor.prototype=Constructor{}
Constructor.prototype.__ptoto__=Object.prototype
Object.prototype.__proto__=null

类的继承

  • 原型链继承
function Animal(){}
function Cat(){}
Cat.prototype=new Animal();//原型链继承
Cat.prototype.name="cat";
//无法向父类构造函数传参
  • 构造继承
function Cat(name)
{Animal.call(this)//此时的this指向父类//只能继承父类实例的属性和方法,不能继承父类原型的实例和方法//所以  new Cat() instanceof Animal ==false//new Cat() instanceof Cat==truethis.name=name
}
  • 实例继承
function Cat(name)
{let cat=new Animal();cat.name=name;return cat;
}
  • 组合继承(构造继承加原型继承)
function Cat(name)
{//构造函数里面加子类的新属性Animal.call(this);this.name=name
}
Cat.prototype=new Animal();
//既可以继承实例的方法也可以继承原型的方法

解决回调地狱

Promise async/await Generator

懒加载与预加载

  • 懒加载

当访问一个页面的时候,把img元素的背景图换位1*1px的图,之后当img元素出现在浏览器可视区域内时,才让图片显示

  • 预加载

提前加载图片,当用户需要查看时,从本地缓存中渲染

JavaScript的new

var cat = new Animal("cat")
//等价于
{var obj={};//创建一个空的临时对象obj.__proto__=Animal.prototype;//绑定构造函数的原型var result = Animal.call(obj,"cat");//得到构造函数的返回对象//若构造函数没有返回对象或者返回的是非对象就返回临时对象return typeof result === 'object'?result:obj;
}

JavaScript垃圾回收

计算机的动态内存不再需要的时候就应该释放,让出内存。

垃圾回收的原理=>考虑某个变量在未来不会被用。

  • 引用计数
let user={name:"simple"
}
//现在user就引用了{name:"simple"}这个对象
user=null;
//现在{name:"simple"}变成不可到达的了,不能访问,JS就会回收他//若是
let user={name:"simple"
}
let admin=usr;
//现在{name:"simple"}就被两个对象引用
user=null;
//即使执行这个,{name:"simple"}还可以通过admin获取,故未被回收//循环引用问题
function func() {let obj1 = {};let obj2 = {};obj1.a = obj2; // obj1 引用 obj2obj2.a = obj1; // obj2 引用 obj1
}
// 当函数 func 执行结束后,返回值为 undefined,所以整个函数以及内部的变量都应该被回收,但根据引用计数方法,obj1 和 obj2 的引用次数都不为 0,所以他们不会被回收。// 要解决循环引用的问题,最好是在不使用它们的时候手工将它们设为空。上面的例子可以这么做:
obj1 = null;
obj2 = null;
  • 标记-清除
/*
垃圾回收器在运行的时候会给存储在内存中的变量都加上标记(所有都加),然后去掉环境变量中的变量,以及被环境变量中的变量所引用的变量(条件性去除标记),删除所有被标记的变量,删除的变量无法在环境变量中被访问所以会被删除,最后垃圾回收器,完成了内存的清除工作,并回收他们所占用的内存
**/

eval 的作用

//eval将js中的字符串转化成为一个表达式,然后执行

前端模块化

将复杂的文件编程成为一个个独立的模块,有利于复用和维护。

  • Commonjs

服务端的模块化规范

var clock=require('clock');
clock.start()//但是这样必须要等待clock模块加载完成才能调用
  • AMD

浏览器端的异步加载模块,先定义所有依赖,然后在加载完成后的回调函数执行

require(['clock'],()=>{clock.start()//但是一开始就把所有依赖写进来不符合书写逻辑
})
  • CMD

用的时候再require

commonjs与es6 module区别

commonjs
静态复制更改,可以修改引入变量的值
var axois=require("axios")//必须加载完成才能使用,而且未使用也要加载module 动态引用
import axios from 'axios'
不允许更改引入变量的值
且需要用到才加载

深拷贝与浅拷贝

首先说说JS的基本数据类型与引用数据类型

  • 基本数据类型(大小固定,放在栈中,栈中存放引用数据类型的地址)
    使用Typeof可以检测基本数据类型,注意 typeof null==object
    String, Boolean,Number,Undefined,Null
  • 引用数据类型(大小不固定,放在堆中)
    使用typeof检测引用数据类型均为 object 要得到确切的 用 instanceof 或者对应类型的原型
    arr instanceof Array==true arr.proto==Array.prototype
    Object(Array,Date,Regexp,Function)

浅拷贝

浅拷贝只会复制指向某个对象的指针,而不复制对象本身,也就是复制对象的引用,新旧对象还是指向的同一块内存,基本数据类型实质是栈的传值,引用数据类型实质是栈的传址

//1.赋值
a=b
//2.Object.assign(des,src) return newDes
let obj={a:"simple"}
let newObj=Object.assign({},obj);//当obj只有一层的时候是深拷贝
//3.函数
function simpleCopy(obj)
{var result=Array.isArray(obj)?[]:{}for(let i in obj){result[i]=obj[i]}return result
}

深拷贝

深拷贝会创造一个一模一样的新对象,新对象与旧对象不共享内存,修改新对象不会改到源对象

//1.手动赋值===太麻烦
//2.JSON转字符串处理  但是不能拷贝函数
var obj1={name:"simple"}
var obj2=JSON.parse(JSON.stringfy(obj))
//3.实现深度克隆
function deepCopy(obj)
{//遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝let result=Array.isArray(obj)?[]:{}//如果是array返回结果为array,否则为objectfor(let i in obj){let value=obj[i]if(typeof value=="object")result[i]=deepCopy(value)elseresult[i]=value}return result
}

实现一个once函数,传入参数只执行一次

function once(fn)
{let flag=true;return function(){if(flag){fn.call(null,arguments);flag=false;}}
}
function test(name)
{console.log(name)
}
test=once(test("simple"));
test()//simple
test()//不执行

与=的区别

对于string,number等基本类型和=是有区别的

不同类型之间进行比较==会将转化为同一类型之后看值是否相等,而===如果类型不同,就是不同

对于Array,Object等引用类型和=没有区别,进行指针地址的比较

对于基本类型与引用类型进行比较,==将引用转为基本进行值比较

setTimeOut setInterval

//setInterval会一直不停执行
//setTimeOut只执行一次

promise

promise对象初始化为pending态
当调用resolve的时候,会由pending=>fulfilled
当调用reject的时候,会由pending=>rejected
promise.then(successValue,failedValue)

promise.all

const p1=new Promise((resolve,reject)=>{resolve(1);
})
const p2=new Promise((resolve,reject)=>{resolve(2);
})
const p3=new Promise((resolve,reject)=>{resolve(3);
})
Promise.all([p1,p2,p3])//接收一个promise数组参数
.then(res=>{console.log(res) //1 2  3
})

手写promise

const PENDING="pending"
const FULFILLED="fulfilled"
const REJECTED="rejected"
function MyPromise(executor)
{//构建promise对象的时候传递executor函数,立即执行//executor接收两个参数,resolve和reject//若executor执行车工则调用resolve,否则rejectlet that=this;//缓存当前promise对象that.status=PENDING;//初始状态that.value=undefined;//fulfilled返回的信息,value保存成功值that.reason=undefined;//reject返回的原因,reason保存失败原因that.onFullfilledCallbacks=[];//成功的回调函数that.onRejectedCallbacks=[];//失败的回调函数  //---均在then方法中,then方法的参数就是成功和失败的回调函数//若成功执行onFullfilledCallbacks,参数是value//失败onRejectedCallbacks,参数是reasonfunction resolve(value){if(value instanceof Promise){//针对resolve返回promise对象的处理return value.then(resolve,reject);}//执行顺序  1.同步代码  2.Promise.then  3.setTimeOut(function(){},0)setTimeOut(()=>{//加settimeout是为了确保onFulfilledCallBack和//onRejectedCallBack异步执行,而且在promise.then之后执行if(that.status==PENDING){//只能由pending=>fulfilled态that.status=FULFILLED;that.value=value;that.onFulfilledCallbacks.forEach(fn=>fn(that.value));}},0)}function reject(reason){setTimeOut(()=>{if(that.status==PENDING){that.status=REJECTED;that.reason=reason;that.onRejectedCallbacks.forEach(fn=>fn(that.reason));}},0)}try{executor(resolve,reject);}catch(e){reject(e)}that.then(onFulfilledCallbacks,onRejectedCallbacks){//then方法链式调用//或者写成MyPromise.prototype.thenif(that.status==FULFILLED){onFulfilledCallbacks(that.value)}else if(that.status==REJECTED){onRejectedCallbacks(that.reason)}}
}

Node的events模块

events模块对应的是观察者模式或者叫发布/订阅模式

const EventEmitter=require('events')
const myEmitter=new EventEmitter()
myEmitter.on("eventName",callback)//订阅-监听事件
myEmitter.emit("eventName",params)//发布-触发事件

Js类型判断

  • typeof =>对基本类型如String,Number,Boolean能判断, typeof null==object 对引用类型判断均为object

  • instanceof left instanceof right 能判断是否为真

function myInstanceof(left,right)
{let proto=left.__ptoto__;let prototype=right.prototype;while(true){if(!proto){return false;}if(proto==prototype){return true;}}
}
  • Object.prototype.toString.call(params)=>[object Number]等结果

forEach、map、filter的区别

  • forEach没有返回值,直接修改原数组,map创建一个新数组使用,有返回值
let arr=[1,2,3,4,5,6]
let newArr=arr.forEach(item=>{return item*item
})//newArr为undefined
let mapArr=arr.map(item=>{return item*item
})
  • filter返回过滤后的数组

js数组去重

  • 双层循环判断
  • indexOf 返回数组某个元素的第一个下标 arr.indexOf(value)!=index
  • ES6 Set去重 new Set(array)
  • reduce
let arr=[1,1,2,2,3,3,4,5,6,7]
let newarr=arr.reduce((pre,cur)=>{if(!pre.includes(cur)){pre.push(cur)}else{return pre;}
},[])

js数组扁平化

var arr=[1,2,[3,4,5,[6,7,8],9],10,[11,12]];
  • 递归实现
function flat(arr)
{let newarr=[]arr.forEach(item={if(item instanceof Array){//contact用于连接连个数组//var a = [1,2,3];//a.concat(4,5)=>[1,2,3,4,5]newarr=newarr.contact(flat(arr));}else{newarr.push(item)}})return newarr
}
  • reduce方法实现
const newarr=function(arr)
{return arr.reduce((pre,cur)=>{pre.concat(Array.isArray?newArr(arr):cur)},[])//最后一个参数为调用reduce的数组
}

暂时性死区

ES6新增了let,const命令,用来声明变量,和var作用差不多,但是旨在所在代码块有效,不存在变量提升,所以声明前调用变量都会报错,这就叫暂时性死区。

if(1)
{temp="abc";let temp;//要报错
}

什么是virtual dom

用JavaScript对象表示DOM树结构,然后区构建一个真正的DOM树,当文档状态发生改变的时候,用新树和旧的树进行比较,记录两棵树的差异,然后将差以构建到真正的DOM树上,实现视图的更新。本质就是在JS和DOM之间做一个缓存

js执行上下文

  • 全局执行上下文

默认的在浏览器中是window对象

  • 函数执行上下文

函数每次调用的时候都会创建一个上下文

var count=0
const fn=(count)=>{count+=1;console.log(count)
}
fn(count)//1
fn(count)//1   因为函数每次调用的时候都会创建新的执行上下文,退出的时候会销毁执行执行上下文const fn=()=>{count+=1;console.log(count)//这个结果就不一样了,用的是全局的上下文}

js函数柯里化

所谓柯里化,就是收集参数的方法,只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。

//1.收集参数=>利用闭包
//2.知道什么时候参数收集完成
function curry(fn)
{let args=[]//保存上一次传递进来的参数return function(){args=args.concat([...arguments]);if(args.length>=fn.length){//参数收集完成,执行函数fn(...args)}return arguments.callee//参数未收集完,继续收集}
}

ES6的Symbol

ES5的对象署名都是字符串,容易造成署名冲突,Symbol就是为了解决这个问题产生的。Symbol是一种新的原始类型数据,返回值是变量,所以只能通过Symbol()调用

let keyName=Symbol("keyName description")
//这样一个简单的Symbol就创建好了!

事件委托与冒泡

事件委托是利用冒泡阶段的运行机制来实现的,就是把一组子元素的事件绑定到父元素上面,可以减少内存消耗,提高效率

for in for of的区别

var arr=[1,2,3,4,5,6,7,8,9]
for(index in arr)
{console.log(arr[index])
}
for(let item of arr)
{console.log(item)
}//使用for in遍历对象
var obj={a:1,b:2
}
//当然Object.key(obj)也能得到对象key数组
for(key in obj)
{console.log(obj[key])
}

正则表达式

  • 匹配电话
var exp=/^1[3,5,7,8,9]\d{9}$/
  • 匹配邮箱
//[\.\w+]*可能遇到有些邮箱@前面有小数点的
var exp=/\w+[\.\w+]*@\w+[\.\w]+/

前端面试题之JavaScript相关推荐

  1. 前端面试题集锦——JavaScript

    前端面试题集锦--JavaScript 1.请你谈谈 Cookie 的优缺点 cookie是存储于访问者计算机中的变量 cookie是浏览器提供的一种机制 可以由JavaScript对其进行控制(设置 ...

  2. 手撕前端面试题【javascript~ 总成绩排名、子字符串频次统计、继承、判断斐波那契数组等】

    前端JavaScript面试题

  3. 前端面试题之JavaScript【this指向】

    JavaScript this指向 全局环境下:this 始终指向全局对象(window), 无论是否严格模式 console.log(this.document === document); // ...

  4. 手撕前端面试题(Javascript~事件委托、数组去重、合法的URL、快速排序、js中哪些操作会造成内存泄漏......

    前端的那些基本标签

  5. 手撕前端面试题【javascript~ 列表动态渲染、无重复数组、数组排序、新数组、创建数组、深浅拷贝、内存泄露等】

    前端的那些基本标签

  6. 手撕前端面试题【javascript~模板字符串、类继承、参数解析器、生成页码等】

    前端的那些基本标签

  7. 「前端面试题系列7」Javascript 中的事件机制(从原生到框架)

    前言 这是前端面试题系列的第 7 篇,你可能错过了前面的篇章,可以在这里找到: 理解函数的柯里化 ES6 中箭头函数的用法 this 的原理以及用法 伪类与伪元素的区别及实战 如何实现一个圣杯布局? ...

  8. JavaScript中的load事件的作用_史上最全的web前端面试题汇总及答案JavaScript之二(二)...

    作者:樱桃小丸子儿 链接:https://www.jianshu.com/p/abadcc84e2a4 JavaScript JS的基本数据类型 number,string,boolean,objec ...

  9. javascript array添加图片_史上最全的web前端面试题汇总及答案JavaScript之二(二)...

    作者:樱桃小丸子儿 链接:https://www.jianshu.com/p/abadcc84e2a4 JavaScript JS的基本数据类型 number,string,boolean,objec ...

最新文章

  1. php mysql execute语法_PHP PDOStatement::execute讲解
  2. 2020年10月GitHub上最热门的开源项目
  3. 基本入门程序编写格式和注意事项
  4. 管理系统页面脚手架(一)
  5. 利用Python进行数据分析--时间序列
  6. Windows下配置QGIS和Python
  7. Wix 3.0正式发布
  8. java获取键盘输入
  9. svg转换pdf用php实现,如何使用javascript在JSPDF中将SVG文件转换为PDF
  10. reuntion 题解
  11. 红外光电开关的原理与实验
  12. 前端框架中的大熊猫Ember
  13. 计算机专业关于Java读书笔记_《Java8学习笔记》读书笔记(四)
  14. UE5/C++ 基于GAS创建攻击伤害 5.1.1准备碰撞体
  15. MarkdownPad2 使用教程
  16. 图片格式网页在线一键转换源码
  17. 淘宝宝贝详情页的优化技巧
  18. CTYZ的树论赛(P5557 旅行/P5558 心上秋/P5559 失昼城的守星使)
  19. javascript中使用枚举定义一个对象进行数据转换
  20. R和pandas实现透视表(pivot; cast/dcast/acast)和逆透视表(melt)过程

热门文章

  1. Java在Quant应用_GitHub - tigerfintech/tiger_quant: Java 实盘量化框架
  2. web前端之——图片上传
  3. MST54XXB 45V,350mA,2.5uA,高PSRR,具有使能功能的低压线性稳压器
  4. 2022个人邮箱注册哪个好?163企业邮箱怎么申请注册个人电子邮箱
  5. SecureFx设置密钥登陆
  6. 【ReID】局部特征
  7. 从零开始,用5年时间,攒够100w,如何够到800w 上海房
  8. 逐步实现一个简易的飞机大战(c++)
  9. sync.Once化作一道光让我顿悟
  10. [linux] bash str字符串转换为int