js面试
js知识点
1.常见的值和引用类型
值:
- undefine
- 字符串
- 数值
- bool
- symbol
引用:
- 对象
- 数组
- null
2.深拷贝与浅拷贝
对于一种问题,比如对象的引用
let obj1 = obj2
obj1.name = “aa”
那么,obj2的name也会因此改变,这就是浅拷贝
这两个对象实例都是指向的同一块内存空间,如果是深拷贝的话,就不会出现这种问题。深拷贝就相当于是把原对象通过递归的方式,将原对象原原本本的复制过去。这样,这个对象实例就变成了一个独立的个体,有着自己的内存空间。
1 | function deepClone(obj={}){ |
上述代码为深拷贝,主要的内容就是对对象中的对象进行递归遍历
3.parseInt
字符串转数字:parseInt
如果遇到字符串拼接问题
return 100+"10"返回的就是一个字符串
如果想要返回纯数字,那么就需要return 100+parseInt("10")
4.什么时候用== 和===
大部分情况下都可以用===
只有在判断空的时候可以用==
因为==会做一个强制的类型转换,可能会得到错误的结果
5.truly和falsely变量

1 | !!0 === false |
只要两次取反结果为true的变量就是truly变量
==if语句()中判断的就是truely变量和falsely变量==
==逻辑判断同理==
6.instanceof类型判断
从字面意思可以看出,instanceof就是看前者是不是后者的一个实例
instanceof会根据原型链一层一层的往上找,如果找到了就会返回一个true
7.隐式原型和显式原型

__proto__是隐式原型prototype是显式原型
8.原型链

对于原型链,我是这么理解的:
xialuo作为student类的一个实例,他的隐式原型就指向student的显示原型,而Student类继承于父类People,所以student也有一个隐式原型去指向父类people的显示原型
1 | log(a) |
9.手写jQuery
1 | class jQuery { |
其中each()中的fn就是回调函数
10.闭包

对于闭包,对自由变量的查找,是从函数定义的地方开始的,然后向上级作用域一层一层的查找,直到window,而不是在执行的地方
11.property和attribute

尽量使用property,这个引起dom渲染的可能性较小
12.转化为数组

Array.prototype.slice.call(转化对象)
13.dom操作性能优化

通过createDocumentFragment(),创建一个文档片段,插入到文档片段的dom元素并不会立即被渲染,会在后续appendChild中统一渲染
14.事件代理(基于冒泡)

由于事件的冒泡行为,事件会向上进行传递

15.跨域问题
1.jsonp方式
因为script是可以跨域的,所以,可以通过script便签去请求网址,通过这个去传数据
另外也可以通过ajax传递

2.CORS通过服务器进行设置
通过服务端设置可信任的端口或者域名
16.手写ajax

1 | function ajax(url){ |
17.本地存储cookie,localstorage,sessionstorage
不同点:
设置值不同
cookie:通过document.cookie=''设置,并且不会覆盖,会类似于push的方式跟在后面,最大存储4k,每次向服务器发送请求都会跟着进去。
localStorage和sessionStorage:
从字面意思就可以看出,sessionStorage是只存在于本次会话,当浏览器关闭时,就会消失。
而localStorage可以存储在本地
这两个最大可以存储5M,通过setItem设置,getItem获取
并且不会随着http请求发送出去
综上,一般用localStorage比较多
需要注意的是,storage只能存储值类型,并不能存储引用类型
- 此时就需要用另一种方法,将引用类型保存为字符串类型
通过JSON.stringify()将对象反序列化,==注意:==比如要严格按照json格式编写'{"name":"123"}'形如这种的,才可以被JSON.parse()给序列化。
思路如下:
- 通过一个固定的命名空间
localStorage.setItem("test",'{"age":"18","name":"jack"}')对象以json格式存储下来 - 通过
localStorage.getItem("test")获取到对象 - 将对象通过
JSON.parse()序列化获取到json数据 - 通过
obj.name = "mike"向obj中追加数据 - 通过
JSON.stringify()将json数据反序列化然后存入localStorage
18.手写防抖
防抖就是防止一个事件多次被触发,比如输入事件,按下键,的事件会被不停的触发,所以需要做出防抖,比如延时一段时间后才去执行某个函数
1 | function debounce(fn,delay = 500){ |
19.手写节流
对于类似拖拽事件,会触发很多事件,这时候就可以使用节流,每隔一段时间触发一次,而不是每动一下就触发一次,这样体感感觉不到,而且性能也有提升.
与防抖的区别应该就是防抖会将定时器清除,而节流不会将定时器清除,而是直接返回
1 | function throttle(fn,delay = 500){ |
20.变量和属性
直接上例子

这里的storage[key] = val,中key必须用[]包裹,这样才能保证key是一个变量,如果使用storage的话,就会变成key是storage的一个属性,对象和属性是不同的,就比如你遍历的时候,可以通过各种key:value进行遍历,但是如果你把本来的key存成属性的话,那么他就不是key:value类型了,他就是所属于该对象的一个属性,而不是一个变量

至于那个第一个图中的为啥不能用.你可以想象下,他传过来的key肯定是个字符串类型,总不能用."key"来接受吧,明显的对不对,所以需要用["key"]来接收,但是调用的话,依然可以用.key,这种操作底层肯定是帮我们做好了。。。
21.执行顺序问题:
直接上结论:process.nextTick>promise.Trick()>promise的回调>async>setTimeout>setImmediate
最开始运行的肯定是放在最顶层的没有包装的
接着就是nextTick,promise,setTimeout,setimmediate。






