0
点赞
收藏
分享

微信扫一扫

js面试必备

一、js数据类型

  • 基本数据类型:String、Number、Boolean、null、undefined、Bigint、Symbol
  • 引用数据类型:Object、Function、Array、Date

二、typeof 和 instanceof

typeof

  • typeof null 返回 “object”
  • typeof 对于引用类型 除了function 会返回function 其他的都是object 对于基本类型 typeof null 为object 其他的都是正常的
  • typeof Array(Array是构造函数 所以返回function) 如果是实例就是对象了

原因:当时,只设计了五种数据类型(对象、整数、浮点数、字符串和布尔值),完全没考虑null,只把它当作object的一种特殊值,32位全部为0。 这是typeof null返回object的根本原因。在js中 二进制的前三位来进行数据类型判断 Object的前三位都是0 null全0 所以就是返回Object

instanceof

三、let、const、var 区别

  • var 存在变量提升,const、let不存在变量提升
  • var 可以重复声明 const、let不可重复声明 且 const 初始化必须赋值 后续不可更改 对象可以改变其中的属性或属性值
  • var 是全局作用域、let和const是块级作用域
  • let 和 const 存在暂时性死区 因为变量不可提升
  • 在函数里面 声明变量不使用关键词 会是全局变量

四、判断一个值的类型

  • 对于基本类型 ,可以使用 typeof 但是null会返回object
  • 对于引用类型 ,除了typeof function 返回 function 其余都是 object 因此对于引用类型 使用instanceof
  • 最全面的 :Object.prototype.toString.call(arg) // 判断arg的类型

五、null 和 undefined 的区别

  • null表示定义了且赋值为null

  • undefined表示定义了但没赋值

六、数组的相关方法

  • Array.from() // 将类数组转化成数组

    • str.split(“,”) 以逗号切割str字符串 返回一个数组 和arr.join(“,”) 相反的效果
    let arr = [2, 3, 1, 4];
    let addFromEnd = arr.splice(0, 1); //包含开始元素 返回被删除的元素
    console.log(arr); //[3,1,4]
    console.log(addFromEnd); //[2]
    
    let arr = [2, 3, 1, 4];
    let addFromEnd = arr.splice(1, 1, 5, 6); //包含开始元素 返回被删除的元素并从此位置替换要加入的内容
    console.log(arr); //[2,5,6,1,4]
    console.log(addFromEnd); //[3]
    
    let arr = [2, 3, 1, 4];
    let addFromEnd = arr.splice(1, 0, 5, 6); //从下标为1开始包括下标 添加元素5,6
    console.log(arr); //[ 2,5,6,3,1,4]
    console.log(addFromEnd); //[]
    
    // arr.fill(value,start,end) start和end是可选项 都不设置则是全部填充值
    let arr=new Array(3);
    arr.fill(0) // 全部填充0
    arr.fill(1,0,2)  // 范围 :0-1下标 不包括2
    console.log(arr);
    
    let arr=[1,2,3,4,5];
    
    let newarr=arr.slice(2,4);
    
    console.log(newarr); // [3,4]
    
    {
        let arr = [1, 2, 3, 4]
        let b = arr.join('-') //可选拼接参数
        console.log(b)//1-2-3-4
        console.log(typeof b)//string
    }
    
    {
        let arr = [1, 2, 3, 4, 5, 6]
        console.log(arr.indexOf(3))//2 
        console.log(arr.indexOf(3, 3))//-1 第一个参数为查找的值 第二个参数为查找的起始位
        console.log(arr.indexOf(8))//-1
    }
    
    {
        let arr = [1, NaN, 100, '42'];
        console.log(arr.includes(1)); //true
        console.log(arr.includes(NaN)); //true
        console.log(arr.includes(1, 3)); //false
    }
    
    let arr = [22, 33, 44, 55];
    arr.forEach((value, index, arr) => {
      console.log("value:" + value);
      console.log("index:" + index);
      console.log(arr);
    });
    
     {
            let arr = [1,2,3,4,5]
            let result = arr.filter(item=> item>2)
            console.log(result)//[3, 4, 5]
        }
    
    {
      let arr = [1,2,3,4,5]
      let result = arr.map(item=> item*2)
      console.log(result)//[ 2, 4, 6, 8, 10 ]
    }
    arr.map((item,index,arr)=>{
        
    })
    // item 是每一项数组的值 index是数组索引 arr是数组
    
    {
        let arr = [1, 2, 3, 4, 5];
        let result = arr.reduce((pre, current) => {
            return pre + current;
        }, 10);
        console.log(result); //10+1+2+3+4+5 10为传入的初始值
    }
    

    案例:

    {
        let arr = ["钱", "钱", "钱", "钱", "富", "林"];
        let arr2 = arr.reduce((prev, cur) => {
            if (cur in prev) {
                prev[cur]++;
            } else {
                prev[cur] = 1;
            }
            return prev;
        }, {});
        Object.keys(arr2).forEach((item) => {
            console.log(item, arr2[item]);
        });
    //钱 4
    //富 1
    //林 1    
    }
    

七、原型和原型链

相关概念

  • 实例的隐式原型指向构造函数的显式原型

  • const a=new A()
    a.__proto__=A.prototype;
    

原型链:

当调用某种方法或者属性时,首先会在自身调用和查找,如果自身没有,就会去它的proto属性中查找,之后会去当前实例所属类的prototype原型对象查找,如果原型对象上也没有 ,由于原型对象上也有proto属性,因此又会重复上述查找方法 Object的原型也就是null 这就是原型链的尽头

  • 原型链式基于隐式原型查找
  • 万物皆可对象 定义在对象原型上的属性 在对象类的原型链中都可以找到 例:
var f = new Function();
var f1 = new f();
Object.prototype.a = 123; // Object原型上的属性可以访问
Function.prototype.b = 234;
console.log(f1.a); // 123
console.log(f1.b); //undefined
console.log(f.b);  // 234

八、JS中的同源策略

同源:同协议、同域名、同端口

同源策略:不同的客户端脚本(javascript,ActionScript)在没有授权的情况下,不能读取对方资源。简单来说,浏览器允许包含在页面A的脚本访问第二个页面B的数据资源,这一切是建立在A和B页面是同源的基础上。

同源策略是浏览器最核心最基本的安全功能 如果缺少了同源策略,浏览器的核心功能会受到影响

解决跨域问题的方法:

九、js的内存回收机制

内存泄漏:不再用到的内存,没有及时释放 ,就叫做内存泄漏

垃圾回收机制:

  • 标记清除 是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。
  • 引用计数 跟踪记录每个值被引用的次数。

引起内存泄漏:

  • 意外的全局变量 解决:严格模式
  • 闭包 解决:可以接触闭包或者删除对这个闭包的引用
  • 没有清理的DOM元素引用
  • 被遗忘的定时器或者回调

十、this指向问题

面向对象语言中 this 表示当前对象的一个引用。

对于函数内部的this指向 做以下判断

this在非严格模式下默认指向 window 严格模式下 undefined

  1. 查看函数在哪被调用。
  2. 点左侧有没有对象?如果有,它就是 “this” 的引用。如果没有,继续第 3 步。
  3. 该函数是不是用 “call”、“apply” 或者 “bind” 调用的?如果是,它会显式地指明 “this” 的引用。如果不是,继续第 4 步。
  4. 该函数是不是用 “new” 调用的?如果是,“this” 指向的就是 JavaScript 解释器新创建的对象。如果不是,继续第 5 步。
  5. 是否在“严格模式”下?如果是,“this” 就是 undefined,如果不是,继续第 6 步。
  6. JavaScript 很奇怪,“this” 会指向 “window” 对象。
image-20220303194804677

十一、函数提升和变量提升

注:函数提升只会提升函数声明 不会提升函数表达式

函数声明: function add(){}

函数表达式:var add=function(){}

  • 函数声明大于变量声明

  • 如果仅是定义没有赋值 就不会覆盖之前的变量或者函数 例:

  • function f(x){
        var x;     // 虽然定义了变量 但没赋值 所以不会覆盖
        console.log(x)  // 5 而不是 undefined
    }
    f(5) 
    
  • 如果函数声明和变量声明同名 但是都没赋值 则优先指向 函数声明 若有赋值就覆盖(覆盖的原因还是变量提升 函数提升的原因)

十二、JSON

json是一种文本格式 不属于任何一种语言 json可以理解为用来传输的文本

Json转化为js对象 :JSON.parse(json);

js对象转化为Json:JSON.stringify(js);

十三、defer 和 async

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yUuDKxo5-1649146282841)(E:\各学习知识点总结\typora图片\image-20220305094921188.png)]

异步一般适合于不操作DOM的脚本

对于有操作DOM的脚本 采用推迟比较好

理解:推迟 就是假设a,b两个进程异步加载 但是 b进程必须等到a进程加载完后才会执行 而异步 是谁先加载块 谁先执行

十四、事件捕获和事件冒泡

DOM事件流:事件捕获阶段 ->处于目标阶段 -> 事件冒泡阶段

  • 事件捕获优先于事件冒泡
  • addEventListerner 默认false 事件冒泡 true 事件捕捉
  • e.currentTarget是事件捕获到的当前元素。 e.target,事件元素 触发的元素

阻止冒泡:

1、 在相应的处理函数内,加入 event.stopPropagation() ,终止事件的广播分发,这样事件停留在本节点,不会再往外传播了

2、在自身处理函数中加入判断

document.getElementById("box1").addEventListener("click",function(event){
    if(event.target == event.currentTarget)  // 判断触发的事件是不是本省
    {
        alert("您好,我是最外层div。");
    }
});

3、事件委托

我们把本来每个元素都要有的处理函数,都交给了其祖父节点body 元素来完成了,也就是说,span,div2,div1 将自己的响应逻辑委托给body,让它来完成相应逻辑,自己不实现相应逻辑,这个模式,就是所谓的事件委托

<script type="text/javascript">
    window.onload = function() {
    document.getElementById("body").addEventListener("click",eventPerformed);
}
function eventPerformed(event) {
    var target = event.target;
    switch (target.id) {
        case "span": 
            alert("您好,我是span。");
            break;
        case "div1":
            alert("您好,我是第二层div。");
            break;
        case "div2":
            alert("您好,我是最外层div。");
            break;
    }
}
</script>

十五、JS模块规范

AMD、CMD、CommonJS、UMD、ESM( JS模块化规范)

十六、严格模式

在严格模式下,在全局执行上下文的this和全局执行上下文的函数内this不再指向window对象;

变量必须先声明再使用,不存在变量提升;

var声明的变量不允许重复声明同一个变量。

不允许使用未声明的变量。对象也是一个变量。

不允许对变量或函数使用delete操作符不允许变量重名
不允许使用八进制

禁止this关键字指向全局对象不可在if内部声明函数

十七、== 比较注意事项

相等和不相等——先转换再比较 (==)

对于相等和不相等操作符:在JS高程中一书中给出如下的基本转换规则
①、如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false转换为0,而true转换为1;
②、如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值
③、如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较

这两个操作符在进行比较时则要遵循下列规则。
①、null 和undefined 是相等的
②、要比较相等性之前,不能将null 和 undefined 转换成其他任何值
③、如果有一个操作数是NaN,则相等操作符返回 false ,而不相等操作符返回 true。重要提示:即使两个操作数都是NaN,相等操作符也返回 false了;因为按照规则, NaN 不等于 NaN
④、如果两个操作数都是对象,则比较它们是不是同一个对象,如果两个操作数都指向同一个对象,则相等操作符返回 true;否则, 返回false

十八、箭头函数特点

  • 箭头函数是匿名函数
  • 不能作为构造函数 不能使用new
  • 没有arguments 用rest参数代替
  • 箭头函数没有原型对象
  • 对于参数和函数体可以省略
  • 箭头函数不绑定this关键字 箭头函数中的this指向的是函数定义位置的上下文this
// 箭头函数不绑定this关键字,箭头函数中的this,指向的是函数定义位置的上下文this。
const obj = {name:"Axx",age:19};
const fn = () => {
    console.log(this); //window
}
fn.call(obj); // this指向还是window,因为箭头函数没有自己的this

function fn2(){
    console.log(this); // fn2普通函数this指向obj
    return () => {
        console.log(this);  //object
    }
}
// 此时箭头函数的this指向obj,因为箭头函数处于fn2函数体当中,而fn2的this指向的是obj,因此箭头函数的this也指向obj
fn2.call(obj)(); 

箭头函数不绑定this关键字 箭头函数中的this指向的是函数定义位置的上下文this

// 箭头函数不绑定this关键字,箭头函数中的this,指向的是函数定义位置的上下文this。
const obj = {name:"Axx",age:19};
const fn = () => {
    console.log(this); //window
}
fn.call(obj); // this指向还是window,因为箭头函数没有自己的this

function fn2(){
    console.log(this); // fn2普通函数this指向obj
    return () => {
        console.log(this);  //object
    }
}
// 此时箭头函数的this指向obj,因为箭头函数处于fn2函数体当中,而fn2的this指向的是obj,因此箭头函数的this也指向obj
fn2.call(obj)(); 
举报

相关推荐

0 条评论