JS基础面试题

95 阅读9分钟

es6新特性

1、块级作用域,可以在块级作用域中声明变量;2、箭头函数,一种新的函数声明方式;3、解构赋值,一种从数组或对象中提取值并赋值给变量的语;4、默认参数,允许在函数定义时为参数提供默认值;5、扩展运算符,可以将数组或对象展开,提取出其中的元素;6、模板字符串;7、类和模块;8、迭代器和生成器;9、Promise对象;10、模块化导入和导出

js的基本数据类型

基本类型:1、String类型,用于表示字符串;2、Number类型,用于表示数字;3、Boolean类型;4、Symbol类型,代表独一无二的值;5、Undefined类型;6、Null类型. 引用类型:7、Object类型。

判断数据类型有那些

1.typeof

可以判断数据类型,它返回表示数据类型的字符串(返回结果只能包括number,boolean,string,function,object,undefined);可以使用typeof判断变量是否存在(如if(typeof !="undefined"){...});特殊变量或类型返回结果为object

2.instanceof

原理 因为A instanceof B 可以判断A是不是B的实例,返回一个布尔值,由构造类型判断出数据类型,一般是用来判断引用数据类型,但不能正确判断基本数据类型,根据在原型链中查找判断当前数据的原型对象是否存在返回布尔类型

3.Object.prototype.toString.call/apply()

可以准确地获取对象的类型信息,这在编写 JavaScript 中的类型检查和处理时非常有用。通常这种方法用于确定对象的类型,以执行相应的操作或处理不同类型的数据。 基本可检测出所以类型

4.constrcutor

有两个作用,一是判断数据的类型, 二是对象实例通过constrcutor对象访问它的构造函数。需要注意,如果创建一个对象来改变它的原型,constructor就不能用来判断数据类型了;

js中处理数组的方法

  • unshift() 向数组的首位添加一个或多个元素,并返回一个新的数组长度。
  • push() 将指定的元素添加到数组的末尾,并返回一个新的数组长度。
  • shift() 从数组删除第一个元素,并返回该元素的值。
  • pop() 从数组删除最后一个元素,并返回该元素的值。
  • concat() 合并多个数组或值,组成一个新的数组。
  • slice() 截取数组中的一部分,返回一个新的数组。
  • fliter() 过滤数组中的元素,返回一个新的数组。
  • sort() 对数组进行排序。
  • reverse() 翻转数组中的元素。
  • indexof() 查找数组中指定元素的下标。
  • find() 查找数组中符合条件的第一个元素。
  • findindex() 查找数组中符合条件的第一个元素的下标。
  • includes() 判断数组中是否包含指定的值。
  • every() 判断数组中的所以元素是否都能通过指定函数的测试。
  • some() 判断数组中是否至少有一个元素通过指定函数的测试。
  • join() 将一个数组的所以元素连接成一个字符串并返回这个字符串。
  • reduce() 计算数组所以元素的总和。
  • map() 对数组中的每个元素进行操作,返回一个新的数组。
  • forEach() 数组循环遍历。

js中的伪数组

  • 无法调用数组的方法,但是有length属性,又可以索引获取内部项的数据结构。
  • arguments、getElementsByTagName等一系列dom获取的NodeList对象,他们都算伪类数组。
  • 转成真数组Array.from() 方法从一个类似数组或可迭代对象中创建一个新的数组实例。
  • slice.call() 利用数组的slice方法,返回一个新的数组。
  • array.prototype.slice.apply() 使用slice返回一个新的数组,用call()或apply()把他的作用环境指向伪数组。

原型与原型链

  • 原型: 原型就是一个为对象实例定义了一些公共属性和公共方法的对象模板。
  • 原型链: 对象之间的继承关系通过构造函数的prototype指向父类对象,直到指向object对象为止形成的指向链条。 通俗讲:原型链是原型对象创建过程的历史记录。

class类的继承

ES6中class(类)作为对象的模块被引入,我们可以通过class关键字定义类,类的本质呢就是function,本质就是构造函数.它可以看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法。 继承:子类通过extends属性继承父类,子类通过super()使用父类的属性,父类的方法直接在子类constructor函数里this调用

for循环下·和forEach的区别

  • 1. for循环for循环是通过 生成 数组的索引下标 循环遍历数组的每一个数据元素 forEach是 JavaScript定义的数组的函数方法 通过 JavaScript底层程序 循环遍历数组的数据元素

  • 2. for循环 可以 通过 break 关键词 来终止循环的执行 for.Each 中 调用执行 break 程序会报错

  • 3. for循环可以通过 控制循环变量 的数值 控制 对于循环的执行 forEach循环 中 参数存储数据都是底层程序进行赋值 无法进行赋值修改等操作

  • 4. for循环 在循环外 可以调用循环变量

  • forEach循环 在循环外 不能调用 循环变量 for循环的执行效率 要 高于 forEach循环

深拷贝与浅拷贝

浅拷贝就是将源对象的属性拷贝一份,如果属性时基本类型值,直接拷贝基本类型值,如果属性是引用类型,则拷贝的是该引用类型在堆中的地址

  • 浅拷贝:

  1. Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。

  2. js数组方法concat和slice

深拷贝

  1. JSON.parse(JSON.stringify(obj));

//递归实现深拷贝

function deepClone(obj){ if(!obj || typeof object !== 'object') return; let newObj = Array.isArray(obj)?[]:{}; for(let key in obj){ //判断对象中是否有该键值 if(object.hasOwnProperty(key)){ newObj[key] = typeof object[key] === "object" ? deepCopy(object[key]) : object[key]; } } return newObj; }

js中声明对象的方式

  • 使用对象字面量(Object Literal)创建对象
  • 使用构造函数(Constructor)创建对象
  • 使用 Object.create() 方法创建对象
  • 使用 class 关键字和构造函数创建对象(ES6 及以上版本)

this的指向以及三种改变this指向方式

this在全局作用域下的指向是window 普通函数this的指向,指向函数的调用 构造函数一般是通过new关键字调用的,其内部的this指向新创建的对象。 箭头函数没有属于自己的this。因此,箭头函数内部使用的this就是箭头函数所在上下文的this

  • 其中的call和apply都只是临时的借用某个对象的this,并且会自动的执行当前的函数。

  • bind方法作用就是永久的将某个对象中的this改变为另一个对象的this,改变之后原本的函数不会立即执行,需要手动的调用。

箭头函数和普通函数的区别

  • 箭头函数:箭头函数如果没有参数,同时函数体的返回值只有一句,则{}和return都可以省略。
  • 普通函数:this总是指向调用它的对象,如果作为构造函数,它指向创建的对象实例
  • 箭头函数:箭头函数的this指向的是父级作用域的this,是通过查找作用域链来确定 this 的值,也就是说看的是上下文的this,指向的是定义它的对象,而不是使用时所在的对象。
  • 普通函数:call()、apply()、bind()等方法能改函数中this的指向
  • 箭头函数:call()、apply()、bind()等方法不能改变箭头函数中this的指向
  • 普通函数:可以作为构造函数,用来创建对象实例
  • 箭头函数:箭头函数不能作为构造函数使用
  • 普通函数:每一个普通函数调用后都具有一个arguments对象,用来存储实际传递的参数。
  • 箭头函数:箭头函数没有自己的arguments,取而代之用rest(剩余)参数...arg来解决
  • 普通函数:具有prototype
  • 箭头函数:没有prototype原型

js事件代理

  • JavaScript事件代理,也称为事件委托,是一种通过将事件处理程序绑定到某个父元素而实现的技术。当子元素触发某个事件时,该事件将被传递到父元素,父元素再根据触发事件的具体子元素来执行相应的操作。

获取元素的方法

  • 通过ID获取(getElementById) 例:document.getElementById('id')
  • 通过name属性(getElementsByName)
  • 通过标签名(getElementsByTagName)
  • 通过类名(getElementsByClassName)
  • 获取html的方法(document.documentElement)
  • 获取body的方法(document.body)
  • 通过选择器获取一个元素(querySelector)
  • 通过选择器获取一组元素(querySelectorAll)

js中的模板字符串

  • 用反引号(`)标识,它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。

js扩展运算符

也称为三个点运算符(…),是在ES6中引入的一种语法。它可以用来在函数调用、数组、字符串、对象等中展开表达式。 1.函数调用中的扩展运算符:
在函数调用时,可以使用扩展运算符将数组或类数组对象展开为独立的参数传递给函数。 2.数组中的扩展运算符:
在数组中,扩展运算符可以将一个数组展开为多个元素。 3.字符串中的扩展运算符:
在字符串中,扩展运算符可以将字符串拆分为字符数组。 4.对象中的扩展运算符:
在对象中,扩展运算符用于将对象的属性和方法展开为新对象。

js防抖截流

JavaScript是事件驱动的, 伴随着大量的触发事件操作。由于JavaScript是单线程工作机制,大量的触发事件在队列中同时处理,有一些频繁的事件处理会造成性能消耗,我们可以使用一些性能优化的方式进行事件的频繁处理。防抖和节流就是JavaScript中性能优化的方式之一。

  • 防抖函数的实现 设计简单的防抖函数思路如下:
    1.事件函数执行,先创建一个定时器
    2.把逻辑代码放到定时器中。
    3.当函数再次触发,清除定时器
    4.创建一个新的定时器即可。
  • 节流函数的实现原理和思路
  1. 记录事件上一次的触发时间。
  2. 获取当前事件触发的时间。
  3. 使用设置的等待时间减去当前时间和上一次时间的差值。
  4. 当计算出来的时间结果小于等于零时,执行对应的逻辑代码。