1.延时加载JS有哪些方式
延时加载 :async defer
例如:<script defer type="type/javascript" src='script.js'></ script>
defer:等html全部解析完成,才会执行js代码,顺次执行的
async: js和html解析是同步的,不是顺次执行js脚本(谁先加载完先执行谁)
2.JS数据类型有哪些
基本类型:string,number,boolean,undefined,null,symbol,bigint
引用类型:object
NaN是一个数值类型,但不是一个具体的数字
null和undefined的区别
null会被隐式转换为0,很不容易发现错误
为了弥补null的坑所以出现了unfefined
null是bject类型,undefined是undefined类型
undefined表示变量未初始化或属性不存在
null 表示明确的无或空值
==和===的区别
==比较的是值
===除了比较值还比较类型
3.JS微任务和宏任务
JS是单线程的 ,同一时间只能执行一个任务
JS代码执行流程:同步执行完 ==》事件循环
事件循环 【微任务,宏任务】
微任务:promise.then
宏任务:setTimeout..
要执行宏任务的前提是清空了所有的微任务
同步的任务都执行完了,才会执行事件循环的内容
进入事件循环:请求,定时器,事件...
总体流程:
同步 ==》 事件循环 【微任务和宏任务】 ==》 微任务 ==》 宏任务
4.JS作用域
除了函数外,JS是没有块级作用域的
作用域链:内部可以访问外部的变量,但是外部不能访问内部的变量
注意:如果内部有,优先查找到内部,如果内部没有就查找外部的,一层一层往外找。
var a =b =10 ==> var a= window.b = 10
前面没有类型 默认是window
JS有变量提升机制(变量悬挂声明)
声明变量的优先级是大于声明普通函数的
------
console.log(str) ⇒ undefined
var str ="你好"
-------
-------
var name = 'a'
(function(){
if(typeof name =='undefined'){
var name = 'b'
console.log('111'+name) --> √
}else{
console.log('222'+name)
}
})
⇒ 111b 因为内部已经有了name
-------
-------
console.log(c) ==>undefined (变量提升)
if(false){
var c= 10
}
console.log(c) ==>undefined (变量提升)
-------
-------
var bar=1
function test(){
console.log(bar) ⇒ undefined
var bar = 2;
console.log(bar) ==>2
}
-------
5.JS对象考题
对象是通过new操作符构建出来的,所以对象之间不相等 (除了引用外)
[1,2,3] === [1,2,3] ==>false
对象的key都是字符串类型
var a ={}
var b =
key :'aa'
}
var c = {
key:'c'
}
a[b]='123' =>给a添加了 [Object Object]:123
a[c]='456' =>重新赋值 a.[Object Object] =456
console.log(a[b]) =>456
对象如何查找属性
查找规则: 先在对象本身 ==》构造函数 ==》对象原型 ==》构造函数原型找 ==》对象上一层原型
每个函数都自带一个prototype【原型】
对象拥有 __proto__
new Fun 该Fun构造函数的原型指向于(new Fun)的原型
new的函数 this执行new
否则指向window
6.判断是不是数组有哪些方法
1.isArray
var arr = [1,2,3];
console.log(Array.isArray(arr)) true
2.instanceof
var arr = [1,2,3]
console.log(arr instanceof Array) true
3.通过原型
var arr = [1,2,3]
console.log(Object.protorype.toString.call(arr).indexOf('Array')!==-1)
4.isProtorypeOf()
console.log(Array.prototype.isPrototypeOf(arr))
5.construct
console.log(arr.constructor.toString().indexOf('Array'))
9.关于slice 和 splice
1.slice是用来截取的
参数可以写slice(3),slice(1,3),slice(-3)
返回的是一个新的数组
2.splice功能:插入,删除,替换
会改变原数组
splice(从哪开始,删几个元素,'插入的元素')
let removed = arr.splice(2,2) //从索引2开始,删除2个元素
arr.splice(2,0,"apple","orange") 从索引2开始添加两个元素
arr.splice(2,2,"apple","orange")从索引2开始替换两个元素
10.关于数组去重
方式一:new set
var arr1 = [1,2,3,1,2,3]
function unique(arr){
return [...new Set(arr)]
}
console.log(unique(arr1))
方式二:indexOf
var arr2 = [1,2,3,1,2,3]
function unique(arr){
var brr = [];
for(var i =0;i<arr.length;i++){
if(brr.indexOf(arr[i])==-1){
brr.push(arr[i])
}
}
return brr
}
11.new操作符具体做了什么
1.创建一个空的对象
2.将空对象的原型,指向于构造函数的原型
3.将空对象作为构造的上下文(改变this指向)
4.对构造函数有返回值的处理判断(如果返回的是基本类型 则忽略 如果是引用类型则返回)
function Fun(age,name){
this.age=age;
this.name=name;
}
function create(fn,...args){
//创建一个空对象
var obj = {};
//将对象的原型指向构造函数的原型
Object.setProtorypeOf(obj,fn.prototype)
//将空对象作为构造函数的上下文
var result = fn.apply(obj,args)
return result instanceof Object >result:obj
}
console.log(create(Fun,18,'张三'))
12.关于闭包
1.闭包是什么
闭包是一个函数加上到创建函数的作用域的链接,闭包 关闭了 函数的自由变量
2.闭包可以解决什么问题
内部函数可以访问到外部函数的局部变量
闭包可以解决的问题
var lis = document.getElementsByTagName('li')
for(vat i = 0;i<lis.length;i++){
(function(i){
lis[i].onclick = function(){
alert(i)
}
})(i)
}
闭包的缺点
变量会驻留在内存中,造成内存损耗的问题
解决:把闭包的函数设置为空
内存泄漏(ie)
13.原型链
原型可以解决什么问题: 对象共享属性和方法
谁有原型:
函数拥有:prototype
对象拥有:__proto__
对象查找属性或方法的顺序
现在对象本身查找->构造函数中查找->对象的原型->构造函数的原型
14.JS的继承有哪些方式
方式一:ES6
class Parent{
constructor(){
this.age = 18
}
}
class Child extends Parent {
constructor(){
super();
this.name='张三'
}
}
let o1 = new Child()
console.log(o1,o1,name,o1,age)
方式二:原型链继承
function Parent(){
this.age = 20
}
function Child () {
this.name = '张三'
}
Child.prototype = new Parent();
let o2 = new Child();
console.log(o2,o2.name,o2.age)
方式三:借用构造函数继承
function Parent(){
this.age = 12
}
function Child(){
this.name = '张三'
Parent.call(this)
}
let o1 = new Child()
console.log(o1,o1.name,o1,age)
15.clal apply bind的区别
可以改变指向
语法:函数.call , 函数.apply ,函数.bind
区别:call apply可以立即执行,bind不会立即执行,因为bind返回的是一个函数需要加()执行
后面的参数是传递的参数
apply第二个参数是数组,call和bind有多个参数需要挨个写
16.深拷贝和浅拷贝
浅拷贝:只复制应用 不复制值 地址是一样的
深拷贝:是复制真正的值 两个地址 递归
function copyObj (obj){
if(Array.isArray(obj)){
var newObj = []
}
var newObj = {}
for(var key in obj){
if(typeof obj[key] ==='object'){
newObj[key]=copyObj(obj[key])
}else{
newObj[key]=obj[key]
}
}
return newObj
}
17.localStorage sessionStorage cookie的区别
sessionStorage.setItem('key','123') :仅在当前浏览器窗口关闭
之前有效 【关闭了浏览器之后就没了】
localStorage.setItem('key','123'): 始终有效 窗口或者浏览器
关闭也有效,所以叫持久化存储
cookie:
var data = new Data()
vat time = 3600*60*60*24
time =data.getTIme() +time
data.setTime(time)
documment.cookie = 'key=789;expires = ' +data.toUTSCtring()+'' //设置过期时间
存储大小限制:cookie 不能超过4K
localStorage,sessionStorage不能超过5M