2021JavaScript面试题(最新)不定时更新(2021.11.6更新)

本文详细梳理了JavaScript面试中的常见知识点,包括数据类型、原型链、数组处理、字符串转换、布尔值转换、对象和数组操作、事件循环、闭包、异步编程、ES6新特性、类型判断、性能优化等。此外,还介绍了前端开发中的面试技巧,如懒加载、预加载、事件处理和对象去重等。适合前端开发者准备面试和巩固基础知识。
摘要由CSDN通过智能技术生成

插个小广告~
字节跳动前端开发工程师-番茄小说内推,校招、社招、实习均可。
欢迎加我q:2679330388,欢迎来撩~

文章目录


说一下JS的基本数据类型

JavaScript的数据类型分为俩种,一种是基本数据类型,一种是引用数据类型

1.基本数据类型

js 一共有六种基本数据类型,分别是 Undefined、Null、Boolean、Number、String,还有在 ES6 中新增的 Symbol 类型。
Symbol 代表创建后独一无二且不可变的数据类型,它的出现我认为主要是为了解决可能出现的全局变量冲突的问题。

2.引用数据类型

引用数据类型统称为 Object 对象,主要包括对象、数组、函数、日期和正则等等。

  • Symbol类型是做什么的?
null 和 undefined 的区别?

undefined 代表的含义是未定义,null 代表的含义是空对象。一般变量声明了但还没有定义的时候会返回 undefined,null主要用于赋值给一些可能会返回对象的变量,作为初始化。

当我们使用双等号对两种类型的值进行比较时会返回 true,使用三个等号时会返回 false。

介绍一下JavaScript 原型、原型链?原型链有什么特点?_

**构造函数原型:**每一个构造函数的内部都有一个 prototype 属性,这个属性时一个指针,指向另一个对象,这个对象包含了可以由该构造函数的所有实例共享的属性和方法。

**对象原型:**当我们使用构造函数新建一个对象后,在这个对象的内部将包含一个指针,这个指针指向构造函数的 prototype 属性对应的值,这个指针称为对象的原型。

原型链

当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念。原型链的尽头一般来说都是 Object.prototype,然后Object.prototype.__proto _ _为null。

image-20210407210035841

Array 构造函数只有一个参数值时的表现?

Array 构造函数只带一个数字参数的时候,该参数会被作为数组的预设长度这样创建出来的只是一个空数组,只不过它的 length 属性被设置成了指定的值。

说一说其他值到字符串的转换规则?toString
  • null 和 undefined 类型 ,null 转换为 “null”,undefined 转换为 “undefined”,
  • Boolean 类型,true 转换为 “true”,false 转换为 “false”。
  • Number 类型的值直接转换,不过那些极小和极大的数字会使用指数形式。
  • Symbol 类型的值直接转换,但是只允许显式强制类型转换,使用隐式强制类型转换会产生错误
  • 对象,会调用Object.prototype.toString()来返回内部属性 [[Class]] 的值,如"[object Object]"。
如何把对象转换成字符串/字符串和对象的相互转换。

对象转字符串 JSON.stringify(obj)
字符串转对象或数组 JSON.parse(str)

其他值到布尔类型的值的转换规则?

利用Boolean对象进行转换

以下这些是假值:

  • undefined
  • null
  • 0和 NaN
  • “”

假值的布尔强制类型转换结果为 false。从逻辑上说,假值列表以外的都应该是真值。

其他值到数字值的转换规则?

Number()函数的转换规则

  • null,返回 0。

  • undefined,返回 NaN。

  • 布尔值,true 转换为 1,false 转换为 0。

  • 数值,直接返回。

  • 字符串:

    • 只有数字,直接转
  • 空字符串,0

    • 其他情况,则返回 NaN。
  • 对象,调用 valueOf()方法,并按照上述规则转换返回的值。

相等操作符 == 比较规则

1、两个简单数据类型,类型不同,转数字比较。

2、一个简单、一个复杂,复杂转简单后比较。

3、两个复杂,比地址。

{} 和 [] 的 valueOf 和 toString 的结果是什么?

valueOf()方法会将对象转换为基本类型,如果无法转换为基本类型,则返回原对象。

toString返回当前对象的字符串形式。

{} 的 valueOf 结果为 {} ,toString 的结果为 "[object Object]"

[] 的 valueOf 结果为 [] ,toString 的结果为 ""
判断数据类型的方法

基本类型判断

在 JavaScript 里 使用 typeof 来判断数据类型,只能区分基本类型,即 “ number ” , “ string ” , “ undefined ” , “ boolean ” , “ object ” ,"function"六种。

typeof '';               // string 有效
typeof 1;                // number 有效
typeof true;             // boolean 有效
typeof undefined;        // undefined 有效
typeof null;             // object 无效
typeof [] ;              // object 无效
typeof new Function();   // function 有效
typeof new Date();       // object 无效
typeof new RegExp();     // object 无效

引用类型判断

区别对象、数组、函数可以使用Object.prototype.toString.call 方法。判断某个对象值属于哪种内置类型。

console.log(Object.prototype.toString.call(123))          // [object Number]
console.log(Object.prototype.toString.call('123'))        // [object String]
console.log(Object.prototype.toString.call(undefined))    // [object Undefined]
console.log(Object.prototype.toString.call(true))         // [object Boolean]
console.log(Object.prototype.toString.call({}))           // [object Object]
console.log(Object.prototype.toString.call([]))           // [object Array]
console.log(Object.prototype.toString.call(function(){})) // [object Function]
console.log(Object.prototype.toString.call(this));        // [object Window]

对象类型判断

instanceof 运算符也常常用来判断对象类型。用法: 左边的运算数是一个object,右边运算数是对象类的名字或者构造函数; 返回truefalse

[] instanceof Array; // true
[] instanceof Object; // true
[] instanceof RegExp; // false
new Date instanceof Date; // true
判断一个变量是否为数组

Array.isArray
Object.prototype.toString.call()
x instanceof Array

Object.prototype.toString的原理

在 Object.prototype.toString 方法被调用时,他会找this对象的[[Class]]属性的值,将这个值与object字符串拼接并返回。

[[Class]]是一个内部属性,所有的对象都拥有该属性。在规范中,[[Class]]的值是一个字符串值,表明了该对象的类型。

typeof null输出什么

输出“object",为什么?

因为不同的对象在底层都表示为二进制,在Javascript中二进制前三位都为0的话会被判断为Object类型,null的二进制表示全为0,自然前三位也是0,所以执行typeof时会返回"object"。

typeof NaN 的结果是什么?

typeof NaN; // “number”

NaN 意指“不是一个数字”(not a number),用于指出数字类型中的错误情况。

NaN != NaN为 true。 NaN==NaN为false

typeof的原理

typeof原理:不同的对象在底层都表示为二进制,在Javascript中二进制低三位存储其类型信息。

  • 000: 对象
  • 001: 整数
  • 010: 浮点数
  • 100:字符串
  • 110: 布尔
instanceof的原理

Instanceof 是通过原型链去查找,找到某个对象的原型对象,使用原型对象的constructor找到构造函数,看看构造函数与Instanceof后面的是否相同,不相同,继续向上查找,直到尽头,找到为True,没找到为false。

0.1 + 0.2 等于多少

0.3000000000000004。不会精确等于0.3。

首先,十进制的0.1和0.2会被转换成二进制的,二进制浮点数表示法并不能精确的表示类似0.1这样的数值,因为浮点数在转化为二进制时,会出现无限循环

0.1 -> 0.0001 1001 1001 1001...(1100循环)
0.2 -> 0.0011 0011 0011 0011...(0011循环)

两者相加之后得到二进制为再转换为十进制,会产生误差。

我想0.1+0.2 精确的等于0.3怎么办

num.toFixed(小数点位数)
先10相加 再除10

小数如何取整,或保留几位小数

可以使用toFixed方法,可把 Number 四舍五入为指定小数位数的数字。

var num = 5.56789;
var n=num.toFixed(2);

输出:

5.57
JavaScript 什么是闭包

闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量。

  • 闭包的用途
  • 闭包的应用场景
闭包的好处

闭包有两个常用的用途。

1.可以让我们函数外部能够访问到函数内部的变量。

2.闭包函数保留了使用的变量对象的引用,保证变量对象不会被回收。

闭包有很多好处,如果我们过多的使用,就会导致大量的变量都被保存在内存中,内存消耗很大,造成网页的性能问题,且容易造成内存泄漏。解决方法是在退出函数之前,将不使用的局部变量全部删除。(至为null这样)

// 解除引用避免内存泄露
function closure(){    
    var div = document.getElementById('div');    
    var test = div.innerHTML;
    div.onclick = function () {
        console.log(test);
    };
    div = null;
}
闭包的应用场景
  • 构造函数的私有属性
  • 函数节流、防抖

私有属性

在函数中使用var来创建变量,这时候在函数外部就无法获取到这个变量,我们可以在函数内部提供一个特权方法来访问这个变量。

function Person(param) {
    var name = param.name; // 私有属性
    this.age = 18; // 共有属性

    this.sayName = function () {
        console.log(name);
    }
}

const tom = new Person({name: 'tom'});
tom.age += 1; // 共有属性,外部可以更改
tom.sayName(); // tom
tom.name = 'jerry';// 私有属性,外部不可获取、更改
tom.sayName(); // tom
!!!节流、防抖了解吗?写一下节流防抖

函数节流

节流是指在一段时间内只允许函数执行一次。我们可以使用定时器实现节流。

函数节流会用在比input, keyup更频繁触发的事件中,如resize, touchmove, mousemove, scroll。throttle 会强制函数以固定的速率执行

// 节流
var throttle = function(func, delay){
    var timer = null;

    return function(){
        var context = this;
        var args = arguments;
        if(!timer){
            timer = setTimeout(function(){
                func.apply(context, args);
                timer = null;
            },delay);
        }
    }
}

防抖

防抖的作用是,一个事件回调函数在一段时间后才执行,如果在这段时间内再次调用则重新计时。

实际应用场景: 搜索框,如果用户不断输入,通过防抖节约请求资源。

一般我是使用lodash的decounce进行防抖。

debounce(方法,时间)

在项目我开发一个备注搜索的时候,就是使用了防抖,避免频繁的发起请求。

原理:内部维护一个计时器timer,返回一个函数,在这个函数里清除计时器并重新计时,计时结束后执行fn函数。

// 防抖
function debounce(fn, delay){
    // 维护一个 timer
    let timer = null;
    
    return function() {
        // 获取函数的作用域和变量
        let context = this;
        let args = arguments;
        
        clearTimeout(timer);// 清除重新计时
        timer = setTimeout(function(){
            fn.apply(context, args);
        }, delay)
    }
}
Symbol类型是做什么的?

SymbolES6 新推出的一种基本类型,它表示独一无二的值。它最大的用途就是用来定义对象唯一的属性名,就能保证不会出现同名的属性,还能防止某一个属性被不小心覆盖。

Symbol的具体用法

通过Symbol()方法可以生成一个symbol,里面可以带参数,也可以不带参数

Symbol 类型的注意点

  • Symbol 函数前不能使用 new 命令,否则会报错。
  • Symbol 函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
  • Symbol值不能与其他类型值运算,不能转数值;可以转字符串和布尔值
  • 不能用.运算符,要用方括号
  • Symbol 作为属性名时,该属性不会出现在 for…in、for…of 循环中,也不会被 Object.keys() 返回。
  • Object.getOwnPropertySymbols 方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。
  • Symbol.for 接受一个字符串作为参数,首先在全局中搜索有没有以该参数为名称的Symbol值。如果有,就返回这个 Symbol 值,否则就新建并返回一个以该字符串为名称的 Symbol 值。
Symbol和Symbol.for的区别

Symbol.for()Symbol()这两种写法,都会生成新的 Symbol。它们的区别是,前者会被登记在全局环境中供搜索,后者不会。Symbol.for()不会每次调用就返回一个新的 Symbol 类型的值,而是会先检查给定的key是否已经存在,如果不存在才会新建一个值。

!!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值