JS 高频面试题

1、JS 的数据类型有哪些,有什么区别

基本数据类型(Undefined、Null、Boolean、Number、String、Symbol)
引用数据类型(对象、数组和函数)
区别:
原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址;
在操作系统中,内存又被分为栈区和堆区,栈区内存由编译器自动分配释放,堆区内存一般由开发着分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收。

2、Symbol 是什么数据类型

Symbol 是 ES6 引入的一种新的基本数据类型,表示独一无二的值。因为是原始数据类型,所有不能new Symbol。
这是使用示例:

let name = Symbol("name");

let person = {
   
  [name]: "张三"
};

console.log(person.name); // 输出:undefined
console.log(person[name]); // 输出:"张三"

在这个例子中,我们使用Symbol创建了一个唯一的键名"name",并使用该键名来存储一个字符串值"张三"。由于Symbol值是唯一的,因此我们可以确保该键名在整个应用程序中是唯一的,从而避免了键名冲突。在访问该值时,需要使用该Symbol值的标识符来访问,而不是直接使用键名。

Symbol 类型的 key 不能通过 Object.keys() 或者 for…in 来枚举,它未被包含在对象自身的属性名集合(property names)之中所以,利用该特性,可以把一些不需要对外操作和访问的属性使用 Symbol 来定义。

let privateData = Symbol("privateData");

let person = {
   
  [privateData]: "这是私密数据"
};

console.log(person.privateData); // 输出:undefined
console.log(person[privateData]); // 输出:"这是私密数据"

for (let key in person) {
   
  console.log(key); // 输出:空行
}

3、encodeURI和encodeURIComponent的区别(了解)

1、编码规则不同:encodeURI()方法不对URI中的特殊字符进行编码,如冒号、前斜杠、问号和英镑符号点,而encodeURIComponent()则对它发现的所有非标准字符进行编码。
2、处理对象不同:encodeURI 只对路径和查询部分进行编码,而 encodeURIComponent 对整个 URI 进行编码。

encodeURIComponent("http://www.example.com?name=hello")
// 'http%3A%2F%2Fwww.example.com%3Fname%3Dhello'
encodeURI("http://www.example.com?name=hello!");
// 'http://www.example.com?name=hello%EF%BC%81'

例如,当你在浏览器地址栏输入一个包含中文的网址时,通常使用的是 encodeURI 来避免中文在网络上无法直接传输的问题。然而,如果你的目的是要将整个 URI 作为参数传递到服务器上,或者需要在其他情况下确保 URI 的完整性,那么你应该使用 encodeURIComponent

4、JS 判断数据类型的方法

方法一、typeof 其中数组、对象、null都会被判断为object,其他判断都正确。

console.log(typeof 'str');           // string
console.log(typeof []);              // object    
console.log(typeof function(){
   });    // function
console.log(typeof {
   });              // object
console.log(typeof undefined);       // undefined
console.log(typeof null); 

方法二、instanceof只能正确判断引用数据类型,而不能判断基本数据类型。

console.log('str' instanceof String);                // false 
 
console.log([] instanceof Array);                    // true
console.log(function(){
   } instanceof Function);       // true
console.log({
   } instanceof Object); 

方法三、Object.prototype.toString.call()

var a = Object.prototype.toString;
console.log(a.call(2));

5、判断数组类型的方法有哪些

方法一、
obj.__proto__ === Array.prototype;
方法二、
Object.prototype.toString.call([]);
方法三、
Array.isArrray(obj);
方法四、
obj instanceof Array

6、typeof和instanceof的区别?

typeof 判断数据类型的原理是通过查看值在内存中的底层表示来确定其类型,返回值是数据类型
instanceof此操作符用于检测一个对象是否是某个构造函数或类构造的实例,返回值是布尔值;
typeof 主要用于检测基本数据类型,对于应用数据类型检测不准确;
而instanceof 用来判断引用数据类型,不能正确判断基本数据类型;

7、为什么使用instanceof不能正确判断基本数据类型

原理是查找左边的_proto_获取到原型对象,判断原型链中是否有和右侧相等;基本数据类型没有构造函数也没有原型链;

function myInstanceof(left, right) {
   
  // 获取对象的原型
  let proto = Object.getPrototypeOf(left)
  // 获取构造函数的 prototype 对象
  let prototype = right.prototype; 
 
  // 判断构造函数的 prototype 对象是否在对象的原型链上
  while (true) {
   
    if (!proto) return false;
    if (proto === prototype) return true;
    // 如果没有找到,就继续从其原型上找,Object.getPrototypeOf方法用来获取指定对象的原型
    proto = Object.getPrototypeOf(proto);
  }
}

8、const 、let、var的区别

一、作用域:let和const具有块级作用域,var不存在块级作用域
二、变量提升: var存在变量提升,let和const不存在变量提升,即在变量只能在声明之后使用,否在会报错
三、重复声明: var声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的遍历。const和let不允许重复声明变量
四、初始值设置: 在变量声明时,var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。
五、使用let 和 var 定义的变量可以修改,而使用const 定义的基本数据类型不可修改,引用数据类型可以修改。

9、使用const定义的数据不能修改吗

其实不能改的不是值,而是变量指向的内存地址,对于基本数据类型来说,其值就保存在变量指向的那个内存地址,因此等同于常量。
而对于引用数据类型来说,保存的只是指针,至于指针指向的数据结构是不能保证的,所以引用数据类型是可以修改的;

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

1、普通函数可以使用函数声明和函数表达式定义,箭头 箭头函数语法更简洁
2、箭头函数没有自己的this,它只会在自己作用域的上一层继承this(你不能在箭头函数中使用new关键字来创建一个新的对象实例,因为箭头函数没有自己的this值)
3、箭头函数继承来的this指向永远不会改变,call()、apply()、bind()等方法不能改变箭头函数中this的指向
4、箭头函数没有自己的arguments(普通函数中,arguments 是一个类数组对象,它包含了传递给函数的参数)监听函数中可以只能通过参数名称来访问
5、箭头函数不能作为构造函数使用,因为没有this

11、JS 模板字面量是什么

JS 模板字面量是 ES6 引入的一种新的字符串表示方式,它使用反引号(`)包裹字符序列,允许在字符串中插入变量、表达式和原始字符串,并且支持多行文本的处理

12、如何实现图片懒加载

图片懒加载就是延迟加载非视口的图片,从而提高页面加载速度,提升用户体验。
window.innerHeight 获取视口的高度,图片顶部到窗口的距离可以使用getBoundingClientRect().top 然后监听页面的scroll方法,获取到img标签,如果图片到顶部的距离小于窗口的高度就应该显示图片。

<body>
        <img data-src="/gift.png">
      <script>
        const images = document.querySelectorAll('img');
        window.addEventListener('scroll',()=>{
   
            images.forEach((item)=>{
   
                const imageTop = item.getBoundingClientRect().top; // 获取图片到顶部的距离
                if(imageTop < window.innerHeight) {
   
                const imgSrc =  item.getAttribute('data-src');
                item.setAttribute('src',imgSrc);
                }
            })
        })
      </script>
    </body>

使用这个方法的问题在于只要滚动就会频繁触发,并且已经展示图片的时候还是会执行;
我们可以使用浏览器提高的构造函数IntersectionObserver来优化

 <body>
        <img data-src="/gift.png">
      <script>
        const images = document.querySelectorAll('img'); 
        // 观察的元素每次进入和离开都会触发
        const callBack = entries => {
   
          entries.forEa
  • 18
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值