1. 延迟加载JS有哪些方式?
defer:等html全部解析完成,才会执行js代码,顺次执行js脚本。
async:async是和html解析同步的,不是顺序执行js脚本(谁先加载完谁先执行)
2. JS数据类型有哪些?
基本数据类型:string、number、boolean、undefined、null、symbol。
引用数据类型:object。
NaN是一个数值类型,但是不是一个具体的数字。
3. null和undefined的区别?
- 作者在设计js的时候先设计的null(借鉴了java的语言)。
- null会被隐式转换成0,很不容易发现错误。
- 先有null后有undefined,出来undefined是为了填补之前的坑。 具体区别:Javascript的最初版本是这样区分的:null是一个表示“无”的对象(空对象指针),转为数值为0;undefined是一个表示“无”的原始值,转为数值时为NaN。
4. ==和===有什么不同?
- ==:比较的是值,通过valueOf转换,valueOf()方法通常由JavaScript在后台自动调用,并不显式地出现在代码中。
- ===:除了比较值,还比较类型。
5. Js微任务和宏任务:
- js是单线程语言。
- js代码执行流程:同步执行完=》事件循环。(同步的任务都执行完了,才会执行事件循环的内容)
- 事件循环中包含微任务和宏任务。
微任务:Promise.then catch finally $nextTick()……
宏任务:setTimeout,setInterval,ajax,fetch……
要执行宏任务的前提是清空了所有的微任务。 流程:同步==》事件循环【微任务和宏任务】==》微任务==》宏任务==》微任务……
6. Js作用域考题:
- 除了函数外,Js是没有块级作用域。
- 作用域链:内部可以访问外部的变量,但是外部不能访问内部的变量。注意:如果内部有,优先查找到内部,如果内部没有就查找外部的。
- 注意声明变量是用var还是没有写(window.)。
- Js有变量提升的机制(变量悬挂声明)。
- 优先级:变量提升 < 传参 < 函数体 < 首行赋值。 6.1 变量提升:
function fn(){
console.log(a)
var a = 1
}
fn() //输出为 undefined
6.2 传参:
function fn(a){
console.log(a)
var a = 1
}
fn(2) //输出为2
从而可以得出,变量提升的优先级低于函数传参。
6.3 函数体:
function fn(a){
console.log(a)
var a = 1
function a(){
return 2
}
}
fn(3) //此时输出为 a函数体
从而可以得出,内部函数体优先级高于函数传参。
6.4 首行赋值:
function fn(a){
var a = 4
console.log(a)
var a = 1
function a(){
return 2
}
}
fn(3) //输出为4
7. js的new操作符到底做了什么?
- 创建了一个空的js对象(即{})。
- 将空对象的原型__prototype__指向构造函数的原型。
- 改变this指向,并将剩余的参数传入。
- 对构造函数有返回值的判断。
function Person(name){
this.name = name;
return 1; // return undefined/NaN/'string'/null
}
let me = new Person('快乐每一天');
console.log(me); // { name:'快乐每一天' }
function Person(name){
this.name = name;
return { age:12 };
}
let me = new Person('快乐每一天');
console.log(me); // { age:12 }
在new的时候,会对构造函数的返回值做一些判断:
1、如果返回值是基础数据类型,则忽略返回值;
2、如果返回值是引用数据类型,则使用return 的返回,也就是new操作符无效;
8. Js对象考题:
- 对象是通过new操作符构建出来的,所以对象之间不相等。(除了引用外)
- 对象注意:引用类型(共同一个地址)。
- 对象的key都是字符串类型。
- 对象如何查找属性、方法:
先在对象本身找===》构造函数中找===》对象原型中找(_proto_)===》构造函数原型中找(prototype)===》对象上一层原型中查找。
[1,2,3] === [1,2,3] //false
var a = {}
var b = {
key:"a"
}
var c = {
key:"c"
}
a[b] = '123';
a[c] = '456';
console.log(a[b]); //456
9. Js作用域+this指向+原型考题:
function Foo(){
getName = function(){ //注意是全局的window
console.log(1)
}
return this;
}
Foo.getName = function(){
console.log(2)
}
Foo.prototype.getName = function(){
console.log(3)
}
var getName = function(){
console.log(4)
}
function getName(){
console.log(5)
}
Foo.getName(); // 2
getName(); // 4
Foo().getName(); // 1
getName(); // 1
new Foo().getName(); // 3
10. Js判断变量是不是数组的方法:
- 方法一:isArray
var arr = [1,2,3];
console.log( Array.isArray( arr ) )
- 方法二:instanceof
var arr = [1,2,3];
console.log( arr instanceof Array )
- 方法三:原型prototype
var arr = [1,2,3];
console.log( Object.prototype.toString.call(arr)) // [object Array]
console.log( Object.prototype.toString.call(arr).indexOf('Array') > -1 )
- 方法四:isPrototypeOf()
var arr = [1,2,3];
console.log( Array.prototype.isPrototypeOf(arr) )
- 方法五:constructor
var arr = [1,2,3];
console.log( arr.constructor.toString().indexOf('Array') > -1 )
11. 闭包:
1. 闭包是什么?
① 函数嵌套函数 ② 函数内部可以引用外部的参数和变量 ③ 参数和变量不会被垃圾回收机制回收
2. 闭包可以解决什么?
① 内部函数可以访问到外部函数的局部变量。 ② 避免全局变量的污染。
3. 闭包的缺点?
① 变量会贮存在内存中,造成内存消耗问题。
解决:把闭包的函数设置为null。
② ie浏览器会造成内存泄漏的问题。
12. 原型链:
1. 原型可以解决什么问题?
对象共享属性和共享方法。
2. 谁有原型?
① 函数拥有:prototype。 ② 对象拥有:_ _proto _ _。
3. 对象查找属性或方法的顺序?
先在对象本身找 --> 构造函数本身找 --> 对象的原型 --> 构造函数的原型中 --> 当前原型的原型中查找。
4. 原型链?
① 是什么?就是把原型串联起来。
② 原型链的最顶端是null。
13.说一下call、apply、bind的区别:
共同点:功能一致
① 可以改变this指向。
② 语法:函数.call()、函数.apply()、函数.bind()
区别
① call、apply可以立即执行。bind不会立即执行,因为bind返回的是一个函数需要加入()执行。
② 参数不同:apply第二个参数是数组。call和bind有多个参数需要挨个写。
14.图片预加载:
我们可以利用浏览器的缓存机制,多个页面访问同一张地址的图片,只会请求图片一次。
可以在A页面偷偷加载B页面的图片。
//创建单个图片加载的方法-包成一个promise
const imgPreloader = url => {
return new Promise((resolve, reject) => {
let image = new Image();
image.src = url
image.onload = () => {
resolve('图片加载成功');
};
image.onerror = () => {
reject('图片加载出错');
};
});
}
/**
* 遍历图片路径,利用promise.all进行并行响应
* @param imgs 图片路径数组
* @returns {Promise<unknown[]>}
*/
const allImgPreloader = imgs => {
let promiseArr = []
imgs.forEach(src => {
console.log(28, src)
promiseArr.push(imgPreloader(src))
})
return Promise.all(promiseArr)
}
export default allImgPreloader