js面试题

本文详细介绍了JavaScript面试中常见的问题,涉及数据类型判断、强制类型转换、函数定义、对象创建、比较运算符、null和undefined的区别、数组和对象识别、DOM操作、事件处理、内存管理、闭包、数组和字符串方法,以及防抖和节流等关键概念。
摘要由CSDN通过智能技术生成

js面试题

1.如何判断js的数据类型

1.1 typeof

基本数据类型
注意:正则、{}、[]、null输出结果为object

1.2 A instance of B

1.3 Object .prototype.toString.call()

使用Object对象的原型方法,toString来判断数据类型

2.强制类型转换跟隐式类型转换

2.1 强制类型转换

1. Number()

2.String()

3.创建函数的几种方式

3.1 函数申明

function a(){}

3.2 函数表达式

let t a= new function()

3.3 箭头函数

let a =()=>{}

4. 创建对象

4.1 字面量创建对象

var obj={
name:‘aaa’,
age:12
}

4.2 构造函数创建对象

function student(name,sex,age){
this.name=name,
this.age=age,
this.sex=sex,
}
var zs=new Student(‘zs’,‘男’,'12) // 返回的是一个对象

4.3 利用Object来创建对象

const obj =new Object()
obj.name=‘zs’;
obj.age=12

5. == 跟 === 的区别

==在使用时会进行隐式强制类型转换
null=undefined //true
null === undefined // false
null === null // true
undefined === undefined // true

6. null和undefined的区别

null表示一个空对象通常用于赋值给可能返回一个对象的变量为初值
typeof null // Object
undefined 使用var跟let申明了一个变量 但是没有初始化
var a;
console.log(a) // undefined
null 加任何数字等于数字 undefined加任何数字等于 NAN

7.什么情况下会返回undefined

1.当访问一个申明但是没有赋初值的变量
2. 当访问一个赋初值为undefined的变量
3. 当访问对象中不存在的属性时
4. 当调用一个没有return的函数
5. 当调用一个return没有内容的函数

8.如何区分数组和对象

8.1 instanceof

[] instanceof Array //true
{} instanceof Object //true

8.2 constructor

([]).constructor //Array
({}).constructor //Object

8.3 Object.prototype.toString.call()

Object.prototype.toString.call([]) // [object Array]
Object.prototype.toString.call([]) // [object Object]

9.多维数字降维

10.怎么获取当前日期

11.什么是类数组(伪数组),如何将其转化为真实的数组

11.1 定义:

1.类数组是一个对象
2.属性名使用数字
3.带有length长度

11.2 特点:

1.不可以使用数组的方法
2.可以转化为真实的数组
3.可以进行循环遍历

11.3 如何转化为真实的数组:

1.Array.form(); es6新增的方法
  let arrr = Array.from(objArr);
2.扩展运算符
 &emsplet Str = ‘hello’;
 &emsplet arr = […Str];
console.log(arr);
3.Array.prototype.slice.call
 &emsplet arr1 = Array.prototype.slice.call(objArr)

12.如何遍历对象的属性

12.1 for in

遍历对象的所有属性 包括继承属性

12.2 Object.keys()

Object.keys() // 属性
Object.values() //属性值
Object.entries() 属性和属性值 不包括继承属性

12.3 Object.getOwnPropertyNam()

遍历对象的属性 不包括Symbol()对象

12.4 Object. getOwnPropertySymbol()

遍历对象的所有Symbol属性

13.dom节点操作

13.1添加

13.1.1 node.appendChild(child)

  node父级 child子级 后面追加元素 类似于组数的push

13.1.2 node.insertBefore(child,指定元素)

  var lili=document.createElement(‘li’);
  ul.insertBefore(lili,ul.children[0]);

13.2移除

13.2.1 removeChild()

13.3移动

13.4复制

13.4.1 cloneNode()

// node.cloneNode() 括号为空或者里面是false 浅拷贝 只复制标签 不复制里面的内容
// node.cloneNode(true) 括号里为true 深拷贝 复制标签复制里面的内容

13.5创建

13.5.1 createElement

13.6查找

1.getElementById
2.getElementsByTagName
3.getElementsByClassName
4.querySelector

14. 阻止默认行为

1.preventDefault()
2 return flase

15.事件补获跟冒泡

  • addEventListener(‘click’,function(){},true)
    第三个参数是true 就是事件补获 是false就是事件冒泡
    当点击一个元素 触发某种事件时 从window对象传导到目标节点
  • 事件补获ducument=>html=>body=>farher=>son 反之就是事件冒泡
  • 阻止事件冒泡 stopPropogation()
    var son=document.querySelector(‘.son’);
    son.addEventListener(‘click’,function(e){
    alert(‘son’);
    e.stopPropagation(); // stop 阻止 propogation 传播
    e.cancelBubble=true // 非标准 cancel 取消 bubble 冒泡
    },false)

16.事件委托

原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点

17.setTimeout与setInterval的用法及区别

  • setTimeout是延时时间到了 就去调用这个函数 只调用一次 就结束了这个计时器
  • setInterval是每隔一段事件重复执行一次代码 如果执行事件超过了事件间隔,setInterval()仍然会在执行完后立即执行下一次代码,而不是等待事件间隔

18.document.write()与innerHTML的区别

  • document.write()会导致页面重新渲染
  • innerHTML是覆盖或者追加动作,同时创建多个元素效率更高,采用数组的形式拼接
    // var inner=document.querySelector(‘.inner’);
    // var arr=[];
    // for(var i=0;i<100;i++){
    // arr.push(‘百度’);
    // }
    // inner.innerHTML=arr.join(‘’) // join 数组转换为字符串

19.this指向问题

  • 在构造函数中,this指向构造函数的实例
  • e.target指向触发事件的对象,this指向事件绑定的对象

20.元素拖动如何实现,原理是什么?

首先mousedown x=e.pageX-login.offsetLeft 得到鼠标在元素内部的位置
然后mouseMove时候 loginX=e.pageX- x 得到物体距离左边界的距离
将left=loginX

21.map()跟forEach的区别

区别主要在于map有返回值,而forEach没有返回值

22.重绘跟回流?如何最小化重绘跟回流

23.延迟加载的方式

23.1 async

  • 延迟脚本
  • 立即下载,但是延迟执行(延迟到整个页面都加载完毕后再执行)
  • 按照脚本的先后顺序执行

23.2 defer

  • 异步脚本
  • 下载完立刻执行
  • 不保证按照脚本的先后顺序执行

23.3 动态创建dom(用的最多)

24.动态创建dom的三种方式

  • ducument.write()
  • innerHTML
  • document.createElement

25.垃圾回收机制

  • 垃圾回收机制是为了防止内存泄漏,将不再使用的变量和对象并将它们从内存中清除,以释放内存空间。
  • 最常见的是标记清除法
  • 工作原理:是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。
  • 工作流程
    –垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记
    –去掉环境中的变量以及被环境中的变量引用的变量的标记。
    –再被加上标记的会被视为准备删除的变量。
    –垃圾回收器完成内存清除工作,销毁那些带标记的值并回收他们所占用的内存空间。

26.内存泄漏的原因

  • 意外的全局变量(在函数内部没有进行var变量申明)
  • console.log
  • 闭包
  • 未清除的定时器
  • 对象的循环引用
  • DOM泄漏(获取到DOM节点之后,将DOM节点删除,但是没有手动释放变量)

27.闭包

闭包的概念:通过函数作用域,内部的函数可以访问到外部函数的变量

  • 优点:
    – 避免全局变量的污染
    – 希望一个变量长期存储在内存中(缓存变量)
  • 缺点:
    – 内存泄漏
    –增加内存使用量
  • 呃呃呃呃呃呃呃呃呃呃呃呃鹅鹅鹅使用场景:封装功能时(需要使用私有的属性和方法),函数防抖、函数节流、函数柯里化、给元素伪数组添加事件需要使用元素的索引值。

28.数组的原生方法

var fruits = [“Banana”, “Orange”, “Lemon”, “Apple”, “Mango”];

  • pop() 删除数组的最后一个元素并返回删除的那个元素(改变原数组)
  • shift() 删除数组的第一个元素并返回删除的那个元素(改变数组)
  • push()向数组的末尾添加一个或者多个元素 返回的是新数组的长度(改变数组)
  • unshift() 在数组的头部添加一个元素 返回的是新数组的长度(改变数组)
  • slice()提取字符串的某个部分,并以新的字符串返回被提取的部分(不会改变数组)
    –var citrus = fruits.slice(1,3); // Orange,Lemon slice
  • splice(何处添加元素,删除元素的个数,添加的新元素)(会改变原数组)
  • splice(start,length)第一个参数开始位置,第二个参数截取长度 (会改变原数组)
  • concat() 数组/字符串拼接 // a.concat(b)
  • join 将数组用标识符链接成字符串返回拼接好的字符串(不改变原数组);
  • reverse() 数组翻转
  • toString() 将数组转换为字符串
  • split() 字符串分割
  • forEach() a.forEach(function(){}) a.forEach(item=>{})
  • every() 主要用于检查数组中每个元素是否符合函数的条件,如果其中有一个不符合,则返回false;
  • indexOf() 主要用于在数组中查找元素,并把元素的位置返回来。

29.字符串方法

  • slice() 截取字符串2个参数,(起始位置,结束位置)
  • substring():截取字符串,(起始位置,结束位置)
  • substr():截取指定位置和长度的字符串,(起始位置,长度)
  • trim():去掉字符串前后所有空格
  • split():把字符串按分隔符分割成数组
  • indexOf():通过字符查找对应下标(首次出现)
  • lastIndexOf():通过字符找最后一次出现的下标值
  • charAt():根据下标找到对应值
  • charCodeAt():通过下标值找到对应字符Unicode编码
  • toLowerCase():字符串转为小写
  • toUpperCase():字符串转成大写

30.如何在JS中动态添加/删除对象的属性?

咱们可以使用object.property_name = value向对象添加属性,delete object.property_name 用于删除属性。
例如:
let user = newObject();
// adding a property
user.name=‘Anil’;
user.age =25;
console.log(user);
delete user.age;
console.log(user);

31.for in与for of的区别

区别一:

  • for(const index in arr){} index 是数组的小标
  • for(const item in arr){} item 是数组的每项的值
    区别二:
  • for…in 循环不仅遍历数字键名,还会遍历手动添加的其它键,甚至包括原型链上的键。for…of 则不会这样
    共同点:
  • 都不能遍历symbol类型的值,遍历symbol类型的值需要用Object.getOwnPropertySymbols()

32.forEach与for of 的区别

forEach不能跳出循环,break 命令或 return 命令都不能奏效;for…of 循环可以与break、continue 和 return 配合使用,跳出循环

33.预解析

预解析就是将所有的变量申明(var)跟函数申明(function)提前到当前作用域的最前面(不提升赋值跟调用函数)
预解析分为变量提升跟函数执行
函数执行就是代码从上到下执行

34.var const let跟暂时性死区

  • var 存在变量提升,可以重复申明,全局作用域
  • const 变量不可改变,一般用于定义常量,存在块局作用域
  • let 不存在变量提升,变量可以改变
  • 暂时性死区:在还没有定义的情况下,使用该变量

35.new操作符干了什么

36. 继承

37.class,extends是什么,有什么作用

38.异步方案

39.图片的懒加载跟预加载

39.1懒加载

  • 定义:在需要的时候才加载图片,延迟加载甚至不加载图片。

  • 原理:利用自定义属性,将图片的自定义scr存到图片标签身上,在需要使用的时候将自定义的scr赋值给src

  • 可视区的高度:window.innerHeight

  • 兼容性写法:let clientHeight=window.innerHeight|| document.documentElement.clientHeight|| document.body.clientHeight;

  • 图片在可视区下面:offsetTop>scrollTop+clientHeight

  • 图片在可视区上面:offsetTop+offsetHeight<scrollTop

  • // 懒加载
    // 参数 : 需要进行预加载的图片的 id (#id) , 类名(.class) ,或标签名(img)
    export default function lazyLoad(imgSelector) {
    const clientHeight = window.innerHeight|| document.documentElement.clientHeight || document.body.clientHeight , // 兼容获取
    const scrollTop = document.documentElement.scrollTop; // 获取页面被卷出去的顶部的高度大小
    let imgsNodes = document.querySelectorAll(imgSelector); // 获取预加载图片列表

    // 遍历检查图片是否在可视区内
    imgsNodes.forEach((v) => {
    if (
    v.offsetTop < clientHeight + scrollTop &&
    v.offsetTop + v.offsetHeight > scrollTop
    ) {
    // 设置正确的 src
    // 实际使用时
    // v.src = v.getAttribute(“srcString”);

    //  这里使用计时器模拟加载时间 ,为能看到是先显示再加载的效果 。
    setTimeout(() => {
      v.src = v.getAttribute("data-srcString");
    }, 800);
    

    }
    });
    }

  • 懒加载优化:节流
    window.onload = function(){
    lazyLoad(‘img’) // 先执行

      let stop = true;  // 节流阀      
      function throttle (){  // 节流函数
       if(stop){   // 如果被节流了
          setTimeout(() => {
              stop = false
              console.log('节流');
          }, 100);
          return 
       }
       stop = true
       lazyLoad('img');
       return;
      }
      window.addEventListener('scroll',throttle)  //  scroll 的执行函数改为节流函数}
    
  • 防抖:我们要的图片得往下滑好几页 。 所以前面的几页图片是可以不需要显示的。或者前面的之前我们已经预览过了,我希望预览比较靠后的图片。那么前面的也可以不用去加载了。那么这种情况就可以使用防抖技术了。
    let stop = true;
    let timeID = ‘’; // 增加一个变量保存倒计时器的 ID
    function throttle (){
    if(stop){
    setTimeout(() => {
    stop = false
    }, 100);
    return;
    }
    stop=true
    // 删除上一个倒计时器
    clearTimeout(timeID)
    // 重新设置倒计时器
    timeID = setTimeout(()=>{
    lazyLoad(‘img’);
    return
    },100) // 延缓 0.1 秒后加载
    }

39.2 预加载:通过js的new Image()

1.创建数组,将图片的src存在数组中
2.循环遍历数组,通过new Image,创建Image对象
3.将数组中的src赋值给img的src
let imgs = [
‘./imgsrc1’,
‘./imgsrc2’,
‘./imgsrc3’,
];

const preloadImg(imgUrls) {
imgUrls.forEach(imgUrl => {
// 生成图片对象
const img = new Image()
img.src = imgUrl
})
}
preloadImg(imgs)

40.防抖和节流

防抖:就是只连续触发事件,在设定的一段时间内只执行最后一次
应用场景:搜索框
实现思路:节流

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值