延迟加载JS有哪些方式?

  1. 延迟加载:asyncdefer
  2. 例如:<script defer type="text/javascript" src='script.js'></script>
  3. defer : html全部解析完成,才会执行js代码,顺次执行js脚本。
  4. async : async是和html解析同步的(一起的),不是顺次执行js脚本(谁先加载完谁先执行)。

JS数据类型有哪些?

基本类型:string、number、boolean、undefined、null、symbol、bigint
引用类型:object
NaN是一个数值类型,但是不是一个具体的数字。

  1. console.log( true + 1 ); //2
  2. console.log( 'name'+true ); //nametrue
  3. console.log( undefined + 1 ); //NaN
  4. console.log( typeof undefined ); //undefined
  5. console.log( typeof(NaN) ); //number
  6. console.log( typeof(null) ); //object

null和undefined的区别

  1. 1. 作者在设计js的都是先设计的null(为什么设计了null:最初设计js的时候借鉴了java的语言)
  2. 2. null会被隐式转换成0,很不容易发现错误。
  3. 3. 先有null后有undefined,出来undefined是为了填补之前的坑。
  4. 具体区别:JavaScript的最初版本是这样区分的:null是一个表示"无"的对象(空对象指针),转为数值时为0undefined是一个表示"无"的原始值,转为数值时为NaN

== 和 === 有什么不同?

  1. == : 比较的是值
  2. string == number || boolean || number ....都会隐式转换
  3. 通过valueOf转换(valueOf() 方法通常由 JavaScript 在后台自动调用,并不显式地出现在代码中。)
  4. === 除了比较值,还比较类型

JS微任务和宏任务

  1. 1. js是单线程的语言。
  2. 2. js代码执行流程:同步执行完==》事件循环
  3. 同步的任务都执行完了,才会执行事件循环的内容
  4. 进入事件循环:请求、定时器、事件....
  5. 3. 事件循环中包含:【微任务、宏任务】
  6. 微任务:promise.then
  7. 宏任务:setTimeout..
  8. 要执行宏任务的前提是清空了所有的微任务
  9. 流程:同步==》事件循环【微任务和宏任务】==》微任务==》宏任务=》微任务...

JS作用域考题

  1. 1. 除了函数外,js是没有块级作用域。
  2. 2. 作用域链:内部可以访问外部的变量,但是外部不能访问内部的变量。
  3. 注意:如果内部有,优先查找到内部,如果内部没有就查找外部的。
  4. 3. 注意声明变量是用var还是没有写(window.)
  5. 4. 注意:js有变量提升的机制【变量悬挂声明】
  6. 5. 优先级:声明变量 > 声明普通函数 > 参数 > 变量提升
  7. ----------------------------------------
  8. function c(){
  9. var b = 1;
  10. function a(){
  11. console.log( b ); // undefined
  12. var b = 2;
  13. console.log( b ); // 2
  14. }
  15. a();
  16. console.log( b ); // 1
  17. }
  18. c(); // undefined 2 1
  19. ----------------------------------------
  20. var name = 'a';
  21. (function(){
  22. if( typeof name == 'undefined' ){
  23. var name = 'b';
  24. console.log('111'+name);
  25. }else{
  26. console.log('222'+name);
  27. }
  28. })() // 111b
  29. ----------------------------------------
  30. function fun( a ){
  31. var a = 10;
  32. function a(){}
  33. console.log( a );
  34. }
  35. fun(100); // 10

JS对象考题

  1. 1. 对象是通过new操作符构建出来的,所以对象之间不相等(除了引用外);
  2. 2. 对象注意:引用类型(共同一个地址);
  3. 3. 对象的key都是字符串类型;
  4. 4. 对象如何找属性|方法;
  5. 查找规则:先在对象本身找 ===> 构造函数中找 ===> 对象原型中找 ===> 构造函数原型中找 ===> 对象上一层原型查找
  6. ----------------------------------------
  7. [1,2,3] === [1,2,3] //false
  8. ----------------------------------------
  9. var obj1 = {
  10. a:'hellow'
  11. }
  12. var obj2 = obj1;
  13. obj2.a = 'world';
  14. console.log(obj1); //{a:world}
  15. (function(){
  16. console.log(a); //undefined
  17. var a = 1;
  18. })();
  19. ----------------------------------------
  20. var a = { k: "1"}
  21. var b = {
  22. key:'a'
  23. }
  24. var c = {
  25. key:'c'
  26. }
  27. a[b] = '123';
  28. a[c] = '456';
  29. console.log( a[b] ); // 456
  30. // a: {k: '1', [object Object]: '456'}
  31. ----------------------------------------

JS作用域+this指向+原型的考题

  1. function Foo(){
  2. getName = function(){console.log(1)} //注意是全局的window.
  3. return this;
  4. }
  5. Foo.getName = function(){console.log(2)}
  6. Foo.prototype.getName = function(){console.log(3)}
  7. var getName = function(){console.log(4)}
  8. function getName(){
  9. console.log(5)
  10. }
  11. Foo.getName(); //2
  12. getName(); //4
  13. Foo().getName(); //1
  14. getName(); //1
  15. new Foo().getName();//3
  16. ----------------------------------------
  17. var o = {
  18. a:10,
  19. b:{
  20. a:2,
  21. fn:function(){
  22. console.log( this.a ); // 2
  23. console.log( this ); //代表b对象
  24. }
  25. }
  26. }
  27. o.b.fn();
  28. ----------------------------------------
  29. window.name = 'ByteDance';
  30. function A(){
  31. this.name = 123;
  32. }
  33. A.prototype.getA = function(){
  34. console.log( this );
  35. return this.name + 1;
  36. }
  37. let a = new A();
  38. let funcA = a.getA;
  39. funcA(); //this代表window
  40. ----------------------------------------
  41. var length = 10;
  42. function fn(){
  43. return this.length + 1;
  44. }
  45. var obj = {
  46. length:5,
  47. test1:function(){
  48. return fn();
  49. }
  50. }
  51. obj.test2 = fn;
  52. console.log( obj.test1() ); //1
  53. console.log( fn()===obj.test2() ); //false
  54. console.log( obj.test1() == obj.test2() ); //false

JS判断变量是不是数组,你能写出哪些方法?

var arr = [1,2,3];
console.log( Array.isArray( arr ) );

console.log( arr instanceof Array );

console.log( Object.prototype.toString.call(arr).indexOf('Array') > -1 );

console.log(  Array.prototype.isPrototypeOf(arr) )

console.log(  arr.constructor.toString().indexOf('Array') > -1 )

slice是干嘛的、splice是否会改变原数组

1. slice是来截取的
    参数可以写slice(3)、slice(1,3)、slice(-3)
    返回的是一个新的数组
2. splice 功能有:插入、删除、替换
    返回:删除的元素
    该方法会改变原数组

JS数组去重

var arr1 = [1,2,3,2,4,1];
function unique(arr){
    return [...new Set(arr)]
}
console.log(  unique(arr1) );
----------------------------------------
var arr2 = [1,2,3,2,4,1];
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;
}
console.log( unique(arr2) );
----------------------------------------
var arr3 = [1,2,3,2,4,1];
function unique( arr ){
    arr = arr.sort();
    var brr = [];
    for(var i=0;i<arr.length;i++){
        if( arr[i] !== arr[i-1]){
            brr.push( arr[i] );
        }
    }
    return brr;
}
console.log( unique(arr3) );

找出多维数组最大值

function fnArr(arr){
    var newArr = [];
    arr.forEach((item,index)=>{
        newArr.push( Math.max(...item)  )
    })
    return newArr;
}
console.log(fnArr([
    [4,5,1,3],
    [13,27,18,26],
    [32,35,37,39],
    [1000,1001,857,1]
])); // [5, 27, 39, 1001]

给字符串新增方法实现功能

String.prototype.addPrefix = function(str){
    return str  + this;
}
console.log( 'world'.addPrefix('hello') )

找出字符串出现最多次数的字符以及次数

var str = 'aaabbbbbccddddddddddx';
var obj = {};
for(var i=0;i<str.length;i++){
    var char = str.charAt(i);
    if( obj[char] ){
        obj[char]++;
    }else{
        obj[char] = 1;
    }
}
console.log( obj ); // {a: 3, b: 5, c: 2, d: 10, x: 1}
//统计出来最大值
var max = 0;
for( var key in obj ){
    if( max < obj[key] ){
        max = obj[key];
    }
}
//拿最大值去对比
for( var key in obj ){
    if( obj[key] == max ){
        console.log('最多的字符是'+key);
        console.log('出现的次数是'+max);
    }
}

new操作符具体做了什么

1. 创建了一个空的对象
2. 将空对象的原型,指向于构造函数的原型
3. 将空对象作为构造函数的上下文(改变this指向)
4. 对构造函数有返回值的处理判断
----------------------------------------
function Fun( age,name ){
    this.age = age;
    this.name = name;
}
function create( fn , ...args ){
    //1. 创建了一个空的对象
    var obj = {}; //var obj = Object.create({})
    //2. 将空对象的原型,指向于构造函数的原型
    Object.setPrototypeOf(obj,fn.prototype);
    //3. 将空对象作为构造函数的上下文(改变this指向)
    var result = fn.apply(obj,args);
    //4. 对构造函数有返回值的处理判断
    return result instanceof Object ? result : obj;
}
console.log( create(Fun,18,'张三')   )

闭包

1. 闭包是什么
    闭包是一个函数加上到创建函数的作用域的连接,闭包“关闭”了函数的自由变量。
2. 闭包可以解决什么问题【闭包的优点】
    2.1 内部函数可以访问到外部函数的局部变量
    2.2 闭包可以解决的问题
            var lis = document.getElementsByTagName('li');
      for(var i=0;i<lis.length;i++){
        (function(i){
          lis[i].onclick = function(){
            alert(i);
          }
        })(i)
      }
3. 闭包的缺点
    3.1 变量会驻留在内存中,造成内存损耗问题。
                解决:把闭包的函数设置为null
  3.2 内存泄漏【ie】 ==> 可说可不说,如果说一定要提到ie

原型链

1. 原型可以解决什么问题
    对象共享属性和共享方法
2. 谁有原型
函数拥有:prototype
对象拥有:__proto__
3. 对象查找属性或者方法的顺序
    先在对象本身查找 --> 构造函数中查找 --> 对象的原型 --> 构造函数的原型中 --> 当前原型的原型中查找
4. 原型链
    4.1 是什么?:就是把原型串联起来
    4.2 原型链的最顶端是null

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 );
// Child {age: 18, name: '张三'} '张三' 18
----------------------------------------
// 方式二:原型链继承
function Parent(){
    this.age = 20;
}
function Child(){
    this.name = '张三'
}
Child.prototype = new Parent();
let o2 = new Child();
console.log( o2,o2.name,o2.age );
// Child {name: '张三'} '张三' 20
----------------------------------------
// 方式三:借用构造函数继承
function Parent(){
    this.age = 22;
}
function Child(){
    this.name = '张三'
    Parent.call(this);
}
let o3 = new Child();
console.log( o3,o3.name,o3.age );
// Child {name: '张三', age: 22} '张三' 22
----------------------------------------
// 方式四:组合式继承
function Parent(){
    this.age = 100;
}
function Child(){
    Parent.call(this);
    this.name = '张三'
}
Child.prototype = new Parent();
let o4 = new Child();
console.log( o4,o4.name,o4.age );
// Child {age: 100, name: '张三'} '张三' 100

说一下call、apply、bind区别

共同点:功能一致
可以改变this指向
语法: 函数.call()、函数.apply()、函数.bind()
----------------------------------------
区别:
1. call、apply可以立即执行。bind不会立即执行,因为bind返回的是一个函数需要加入()执行。
2. 参数不同:apply第二个参数是数组。call和bind有多个参数需要挨个写。
----------------------------------------
1. 用apply的情况
var arr1 = [1,2,4,5,7,3,321];
console.log( Math.max.apply(null,arr1) )
2. 用bind的情况
var btn = document.getElementById('btn');
var h1s = document.getElementById('h1s');
btn.onclick = function(){
    console.log( this.id );
}.bind(h1s)

sort背后原理是什么?

V8 引擎 sort 函数只给出了两种排序 InsertionSort 和 QuickSort,数量小于10的数组使用 InsertionSort,比10大的数组则使用 QuickSort。
之前的版本是:插入排序和快排,现在是冒泡

原理实现链接:https://github.com/v8/v8/blob/ad82a40509c5b5b4680d4299c8f08d6c6d31af3c/src/js/array.js
***710行代码开始***

深拷贝和浅拷贝

共同点:复制

1. 浅拷贝:只复制引用,而未复制真正的值。
var arr1 = ['a','b','c','d'];
var arr2 = arr1;

var obj1 = {a:1,b:2}
var obj2 = Object.assign(obj1);

2. 深拷贝:是复制真正的值 (不同引用)
var obj3 = {
    a:1,
    b:2
}
var obj4 = JSON.parse(JSON.stringify( obj3 ));

//递归的形式
function copyObj( obj ){
    if(  Array.isArray(obj)  ){
        var newObj = [];
    }else{
        var newObj = {};
    }
    for( var key in obj ){
        if( typeof obj[key] == 'object' ){
            newObj[key] = copyObj(obj[key]);
        }else{
            newObj[key] = obj[key];
        }
    }
    return newObj;
}
console.log(  copyObj(obj5)  );

localStorage、sessionStorage、cookie的区别

公共点:在客户端存放数据
区别:
1. 数据存放有效期
        sessionStorage : 仅在当前浏览器窗口关闭之前有效。【关闭浏览器就没了】
        localStorage   : 始终有效,窗口或者浏览器关闭也一直保存,所以叫持久化存储。
        cookie                 : 只在设置的cookie过期时间之前有效,即使窗口或者浏览器关闭也有效。
2. localStorage、sessionStorage不可以设置过期时间
     cookie 有过期时间,可以设置过期(把时间调整到之前的时间,就过期了)
3. 存储大小的限制
    cookie存储量不能超过4k
    localStorage、sessionStorage不能超过5M

    ****根据不同的浏览器存储的大小是不同的。