目录
- 前言
- 理论篇
- 1.js的单线程
- 2.js的数据类型
- 3.js的内存泄漏
- 4.js的宏任务与微任务(事件循环机制)
- 5.js的作用域与作用域链
- 6.js的闭包
- 7.ES6新增
- 8.原型和原型链
- 8.深浅拷贝
- 9.js的防抖和节流
- 10.js中的this指向
- 11.改变this指向的call、apply、bind
- 12.事件流
- 13.DOM与BOM
- 14.let、const、var的区别
- 15.普通函数与箭头函数的区别
- 16.回调函数和回调函数存在的问题
- 17.浏览器跨域
- 18.new的作用
- 19.Json
- 20. http常见状态码
- 21.promise
- 22.Ajax
- 23.for-in和for-of
前言
明天面试,大晚上整理js。希望能拿下!!!
CSS面试可移步:找工作第二弹——挑战CSS重难点一篇就够
理论篇
1.js的单线程
本质区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位。
包含关系:一个进程至少有一个线程,线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
JS是单线程的原因主要和JS的用途有关,JS主要实现浏览器与用户的交互,以及操作DOM。
如果JS被设计为多线程,如果一个线程要修改一个DOM元素,另一个线程要删除这个DOM元素,这时浏览器就不知道该怎么办,为了避免复杂的情况产生,所以JS是单线程的。
2.js的数据类型
js的数据类型有七种:
Number、String、Undefined、Symbol、Boolean、Null、Object。
其中,Symbol是ES6中引入的一种新的基本数据类型,用于表示一个独一无二的值。
三种原始类型的值——数值、字符串、布尔值——在一定条件下,也会自动转为对象,也就是原始类型的“包装对象”。
3.js的内存泄漏
理解:无用的内存还在占用,得不到释放和归还,比较严重的时候,无用的内存还会增加,从而导致整个系统卡顿,甚至崩溃。
出现原因:
意外的全局变量;
DOM元素清空时,还存在引用;
闭包;
遗忘的定时器。
优化:
全局变量先声明在使用;
避免过多使用闭包;
注意清除定时器和事件监听器。
4.js的宏任务与微任务(事件循环机制)
同步任务是指在主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务。
异步任务指的是,不进入主线程、而进入"任务队列"的任务,只有等主线程任务执行完毕,"任务队列"的任务才会进入主线程执行。
异步任务分为宏任务和微任务。同一作用域微任务队列优先于宏任务队列执行,只要微任务队列中还有任务,宏任务队列就只会等待微任务队列执行完毕后再执行。
常见的宏任务:settimeout setInterval script(最外层的script标签);
常见的微任务:promise (async await)。
5.js的作用域与作用域链
作用域:
在ES6之前,js只有全局作用域和函数作用域。ES6之后,js拥有了块级作用域。规定变量和函数的可使用范围称为作用域
全局作用域:
在任何地方都能访问到的对象
局部作用域:
又称函数作用域,仅供函数内部访问
变量作用域:
分为全局变量和局部变量。其中,全局变量使在全局作用下的变量,局部变量是在局部作用域下的变量。
注意,如果在函数内部没有声明但是被赋值的变量也是全局变量,这个需要特别记忆:
全局变量存放在内存中,只有浏览器关闭时才会销毁,比较占内存资源;而局部变量,当程序执行完毕后就会被销毁,比较节约内部资源。所以我们更喜欢使用局部变量。
作用域链:内部函数访问外部函数的变量,采取的是链式查找的方式来决定取哪个值,这种结构我们称为作用域链。
详情可见:一文搞懂js的作用域与作用域链
6.js的闭包
如果一个函数访问了此函数的父级及父级以上的作用域变量,那么这个函数就是一个闭包。
//闭包指有权访问另一个函数作用域中变量的函数
//fun这个函数作用域,访问了fn中的局部变量num,则产生闭包
function fn() {
var num = 10;
function fun() {
console.log(num);
}
fun();
};
fn();
闭包的作用:访问函数内部变量,在内存中一直保存。
闭包满足的条件:
访问所在作用域、函数嵌套、在作用域中被调用。
闭包的特点:
被闭包函数访问的父级及以上的函数的局部变量(如范例中的局部变量 i )会一直存在于内存中,不会被JS的垃圾回收机制回收。
闭包函数实现了对其他函数内部变量的访问。(函数内部的变量对外是无法访问的,闭包通过这种变通的方法,实现了访问。)
缺点:内存泄漏。
7.ES6新增
let、const加入;解构赋值,模板字符串;箭头函数;展开运算符;
class类中不再像ES5一样利用原型链实现继承,而是引入Class的概念;
Promise是一种新的异步解决方案,解决地狱回调,比传统回调更灵活;async,await也可以结合Promise使用(提高代码可读性);
Symbol是一种基本类型。Symbol 通过调用symbol函数产生,它接收一个可选的名字参数,该函数返回的symbol是唯一的;
Proxy代理使用代理(Proxy)监听对象的操作,然后可以做一些相应事情;
Set是类似于数组的数据集合,无序,插入删除速度快,元素不重复,查找速度快;
Map是一个类似对象的数据结构,和对象不同的在于它的key可以是任意类型,但是对象只能使用string和symbol类型,Map的存储关联性更强;
8.原型和原型链
原型:
原型就是一个为对象实例定义了一些公共属性和公共方法的对象模板。
原型链:
8.深浅拷贝
浅拷贝:只拷贝
深拷贝:深拷贝拷贝多层,每一级别的数据都会拷贝
9.js的防抖和节流
防抖:当事件被触发,执行一个定时器,定时器结束后再成功触发。这样可以防止事件被频繁触发。
特点:频繁触发,但只执行一次;
节流:减少事件的触发频率,有选择性执行一部分事件。每隔一段时间触发一次。
10.js中的this指向
1.在script中的this指向的都是window;
2.箭头函数中的this都指向上下环境的this指向;
3.对象属性的this 指向对象外上下文环境的this;对象方法(普通函数)中的this,指向当前对象(谁执行该方法,this就指向谁)
11.改变this指向的call、apply、bind
call:调用fn.call时会将fn中的this指向修改为传入的第一个参数thisArg;将后面的参数传入给fn,并立即执行函数fn。
apply:修改this指向,并立即执行fn。区别在于传参形式不同,apply接受两个参数,第一个参数是要指向的this对象,第二个参数是一个数组,数组里面的元素会被展开传入fn,作为fn的参数。
bind:fn.bind的作用是只修改this指向,但不会立即执行fn;会返回一个修改了this指向后的fn。需要调用才会执行:bind(thisArg, arg1, arg2, arg3, …)()。bind的传参和call相同。
12.事件流
事件流指从页面中接收事件的顺序。事件流模型分为两个部分:分别是冒泡型事件流,捕获型事件流。
捕获:捕获阶段指找目标元素的过程,这个找的过程,是从最大的document对象到html,再到body,直到目标元素。
目标阶段;
冒泡:当目标元素的事件执行结束后,再从目标元素,到他的父元素。。。body、html再到document的过程,是冒泡阶段。
阻止事件冒泡:
e.stopPropagation();
vue中.stop和.prevent可以实现
13.DOM与BOM
DOM:文档对象类型,用于网页的方法和接口;
BOM:浏览器对象类型,用于处理浏览器交互的方法和接口。
14.let、const、var的区别
var:存在变量提升,可以先去声明再去使用,一个变量可多次声明,后面的声明会覆盖前面的声明,var也可也是全局变量,let,const都是局部;
let:不存在变量提升,let声明变量前,该变量不能使用
const:const声明一个只读的变量,声明后,值就不能改变(引用类型地址不变即可值可改变);复合类型可以改变属性。
15.普通函数与箭头函数的区别
外形不同;
普通函数可以有名字,但是箭头函数一定是匿名函数;
普通函数可以用于构造函数,箭头函数不行;
this指向不同,普通函数指向调用它的对象,箭头函数中的this继承而来,指向在定义它时所处的对象;
箭头函数不具备原型和super。
16.回调函数和回调函数存在的问题
把函数当作一个参数传到另外一个函数中,当需要用这个函数是,再回调运行()这个函数.
回调函数是一段可执行的代码段,它作为一个参数传递给其他的代码,其作用是在需要的时候方便调用这段(回调函数)代码。(作为参数传递到另外一个函数中,这个作为参数的函数就是回调函数)
理解:函数可以作为一个参数传递到另外一个函数中。
特点:不会立刻执行,且是一个闭包。
问题:this指向,指向离它最近function调用者,箭头函数可以解决回调函数this不名的问题。
回调函数出现的原因:JavaScript 是事件驱动的语言。这意味着,JavaScript 不会因为要等待一个响应而停止当前运行,而是在监听其他事件时继续执行
17.浏览器跨域
为什么阻止跨域:同源策略(解决网络安全问题);
解决跨域:jsonp、跨域资源共享、请求头。
18.new的作用
先创建一个空对象,然后把this指向该对象,且这个this继承了该对象的原型。
属性和方法也被加入这个对象中。
19.Json
Json是数据交换格式。
JSON 字符串转换为 JSON 对象
let obj = JSON.parse(str);
JSON 对象转换为 JSON 字符串
let obj = JSON.stringify(str);
20. http常见状态码
200:正常;
4xx:标识客户端错误,如400,请求语法错误,403一般是跨域;404一般是找不到资源;
5xx:服务器错误,执行请求发生错误。
21.promise
es6引入解决地狱回调问题,可以链式调用,非常灵活。
状态有三种:pedding、resolve(成功)、reject(失败)。
Promise.finally() finally 方法用于不管 Promise 的状态变为什么,都会执行它内部的函数。
Promise.all()和promise.race():
Promise.all() 的作用是接收一组异步任务,然后并行执行任务,等所有任务执行完之后再执行回调
Promise.all() 传入一组 Promise 数组,只有当所有的 Promise 状态都成功才返回成功,只要有一个失败就返回失败的 Promise 状态
Promise.race() 的作用是接收一组异步任务,然后并行执行任务,只留取第一个完成的任务,其他任务任然会执行,只不过执行结果会被抛弃
Promise.race() 传入一个 Promise 数组,返回的结果由第一个执行完成的 Promise对象 的结果来决定
promise本身是同步,then、catch是异步。
22.Ajax
1. 创建 ajax 对象
const ajax = new XMLHttpRequest();
2. 创建 ajax 请求 (设置请求的方法和请求地址) open
ajax.open('get', 'http://localhost:8080/server?a=100&b=200');
3. 发送请求 send
ajax.send();
4. 处理服务器端返回的结果 onreadystatechange事件
readystate:五个值 0 1 2 3 4,为4的时候代表数据已经接收完成
status:状态码 200 为成功
if(ajax.readystate === 4 && ajax.status >= 200 && ajax.status < 300) {
表示成功,可以写相应的逻辑了
}
23.for-in和for-of
都用于遍历数组。