原生JS面试题整理(2023年)_概念题01

发布时间:2024年01月24日

面试题背诵,回答的思路和模板,思路清晰

1、基本类型和引用类型的区别

(分别从内存,赋值,函数传参的角度描述)

答: 1)、内存的角度: 基本类型在内存中,占据一块空间,空间里存储的就是值,所以也叫,值类型。获取值是属于直接获取 引用类型在内存中,占据两块空间,第一块存储的是地址,第二块存储的是值。也叫地址类型。获取数据是属于间接取值。 2)、赋值: 基本类型:赋的就是值 引用类型:赋的就是地址 3)、函数传参:(等价于把实参赋值给形参) 基本类型:传的是值 引用类型:传的是地址

4)、

基本类型有:Undefined、Null、Boolean、Number、String、Symbol,还有:Bigint,

引用类型有:统称为 Object 类型。

5)、可以写应用场景:

number:表示数字,如:年龄,成绩,金额,等会做加减乘除,比较大小等数学运算的数据

string:非数字信息的描述

boolean:表示是否(两种情况)

Symbol:表示唯一性时

引用类型:表示复杂的数据时,即:一个数据中包括了若干个信息时。

2、Undefined和null的区别

相同点:

都是数据类型,隐式转换为boolean类型时都是false。

概念上的区别:

1)、undefined:是JavaScript的数据类型,表示定义变量后,没有赋值,表示值的缺失 2)、null:对象没有引用的值,即就是:引用类型里没有存储地址。Null还可以用来清除堆区的标记,防止内存泄漏。表示对象的缺失

代码示例:

1) undefined:
?
var a; ? //JavaScript中定义一个变量,没有赋值时,默认为undefined
console.log(typeof a); // undefined
console.log(b); // 报错,因为b没有定义。所有,在浏览器的控制台中会报 b is not defined 
?
2) ?null:
?
var person = null;//定义了一个引用类型,没有指向。
console.log(person); //输出null。
console.log(typeof person);//输出object,person的数据类型是Object,值是null
?

typeof的结果不同

1)、typeof undefined 的结果是undefined

2)、typeof null 的结果是object,所以,它个对象有关系。表示对象的缺失。

场景不同:

1)、undefined:

  1. 变量声明且没有赋值

  2. 获取对象中不存在的属性

  3. 函数需要实参,但是调用时没有传值,形参是undefined

  4. 函数调用没有返回值或者return后没有数据,接受函数返回值的变量

2)、null:

  1. 对象不存在就是null

  2. 手动设置变量的值或某一个属性值为 null

  3. JS 获取 DOM 元素,如果没有获取到指定的元素对象,返回 null

  4. 正则捕获时,如果没有捕获到,返回 null

  5. Object.prototype.proto 的值是 null

  6. document 和 body 很多属性都是 null

02JavaScript面试系列_undefined和null变量类型的理解_分别定义null类型变量和undefined类型变量,并使用alert()函数继续输出-CSDN博客

3、==和===的区别

1、相同点:

都是用来判断两个数据是否相等。

2、判断原理不同的:

===(恒等) 1、如果类型不同,就[不相等] 2、如果两个都是数值,并且是同一个值,那么[相等]。 3、如果两个都是字符串,每个位置的字符都一样,那么[相等];否则[不相等] 4、如果两个值都是true,或者都是false,那么[相等]。 5、如果两个值都引用同一个对象或函数,那么[相等];否则[不相等]。 6、如果两个值都是null,或者都是undefined,那么[相等]。

==(等同) :

1、如果两个值的类型相同,则按照===的思路进行比较

2、如果两个值的类型不同,先做隐式转换,把两个数据转换成同种类型,再进行判断。所以,给大家的感觉是不判断类型。

隐式转换规则:

 ? ? ? ? ```js

a、如果一个是null、一个是undefined,那么[相等]。 b、如果一个是字符串,一个是数值,把字符串转换成数值再进行比较。 c、如果任一值是 true,把它转换成 1 再比较;如果任一值是 false,把它转换成 0 再比较。 d、任何其他组合,都[不相等]。 ```

4、js的声明提升

答: js在预编译阶段,会对声明进行提升,如:声明变量(var),声明函数(function 函数名(){}) 1)、用声明的方式定义变量或者函数,会有提升 2)、声明的变量和函数会提升当前作用域的最顶端。 3)、变量声明,只提升声明不提升赋值;

5、Var、Let,const的区别?

答: 相同点:

这三个关键字都是用来定义变量的 不同点: 1)、var定义的变量会声明提升,let和const定义变量不会声明提升 2)、var定义的变量作用域是全局作用域和函数(局部)作用域,let和const是块级作用域(所在花括号) 3)、var定义的全局变量是window对象的属性,let和const定义的全局变量不是window的属性 4)、var可以定义多个同名的变量,let和const不行 5)、let有暂时性死区 6)、let在循环里,可以暂存循环变量。 7)、const定义的变量是只读的。const修饰的是直接指向(修饰)的内存。

JavaScript面试题,let和var的区别,let和const是什么意思?_let可以定义全局吗-CSDN博客

JavaScript面试题,let和const是什么意思?_在js中let和const是做什么的-CSDN博客

6、const 定义一个数组,改变下标0的值,会报错吗

不会报错,const修饰的是数组,而不是数组的元素。

补充:const修饰引用类型时,都修饰的是地址。而不是数据。

<script type="text/javascript">
 
//const修饰的变量是只读,不能修改的,即是常量
//const修饰的是直接指向(修饰)的内存
 
function testf1(){
    //1、const修饰的变量是只读,不能修改的,即是常量
    //const temp1 = 100;//定义了一个变量temp1,赋值为100,const表示以后不能再修改了
    //temp1 = 200;//这句话会报错,不能给只读变量赋值(Assignment to constant variable.)
 
    //2、const修饰的是直接指向(修饰)的内存
    const arr = [12,23,34];//引用类型在内存中是两块区域,const修饰的是arr(arr是在栈区)
    arr[0]=100;//修改的是堆区的内存
    console.log(arr);
    arr = [1,2,3];//这句话要报错,因为,这句话像改变arr(栈区)的地址
    
}
 
window.onload = function(){
    testf1();
}
</script>
 

7、作用域和作用域链

作用域:,就是变量起作用的区域(范围)。或者说,js代码执行时,查找变量的范围。

作用域链::当js编译器在寻找变量时,先在最近的作用域(花括号)里找,如果找不到,则朝上一级作用域(花括号)里找,依次类推,直到找到或者找不到为止。这就是作用域链。

详细请阅读:原生js面试题:作用域和作用域链,let声明的全局变量不是window对象的属性_有四个作用域(scope),分别是global(全局)、script(脚本)、local(局部)、b-CSDN博客

8、数组的api

9、请描述你对事件流的理解

答:事件流就是事件的流向。事件流分为三个阶段:捕获阶段,事件源,冒泡阶段。

https://blog.csdn.net/jiang7701037/article/details/81481550

10、事件委托

1)、原理和思路:

利用dom事件的冒泡,完成,把dom元素的事件由父元素进行处理。即:在父元素进行事件绑定,完成子元素想要完成的功能。并在父元素的事件处理函数里,使用事件对象的target来判断是否为子元素触发事件。

2)、优点:

减少了代码量

让动态添加的子元素也会具有事件的功能。即:子元素的dom操作,不会影响事件绑定。

3)、示例:

假设一个ul标签里有5个li,请使用事件委托的方式完成,点击每个li,显示每个li里的内容

Ul.onclick = function(event){
 ? ?Let e = event ||window.event;
 ? ?if(e.target.tagName.toLowerCase()==”li”){
 ?      Console.log(e.target.innerHTML);
 ?  }
}

11、this的理解

1、是什么?

this是函数的内置对象。this是代名词。this代表谁,需要看场景(上下文),在js中函数就是this的场景。所以,this一般都是出现在函数内部(其实这个本质是作用域)。

2、this的几种情况(静态的描述) 以下情况所说的函数是非箭头函数。

1)、当this所在函数是事件处理函数时,this表示事件源。

2)、当this所在函数是构造函数时,this表示new出来的对象。

3)、当this所在函数是实例(对象)的方法时,this表示调用该方法的对象。

4)、当this所在函数是全局声明的函数时,

4.1)、非严格模式下:this表示window。(其实这个点和第三点一样)。因为,全局函数都是window对象的方法

4.2)、严格模式下:this是undefined。

5)、this在script标签里,表示window。

3、真正的this,需要看调用(深深的知道就行,面试时,可以不用回答这个)如:。

1)、call,apply,bind是可以改变this指向的。

2)、所谓的构造函数,我也可以不用new调用把。

3)、所谓的全局函数,我也可以把它赋给事件属性。

4、箭头函数是没有this的。

既就是:在判断this指向时,不要把箭头函数当函数看待。

一般人我不告诉他:箭头函数在编译的原理里是词法分析域

12、call,apply和bind的区别

一、文字描述:
1、相同点:

三个函数都会改变this的指向(调用这三个函数的函数内部的this)

2、不同点:

1)、bind会产生新的函数,(把对象和函数绑定死后,产生新的函数),新的函数的所有调用都会是绑定的this。

2)、call和apply不会产生新的函数,只是在调用时,绑定一下而已。

3)、call和apply的区别,第一个参数都是要绑定的this,apply第二个参数是数组(是函数的所有参数),call把apply的第二个参数单列出来。

二、示例代码:
?
<body>
 ? ?<!-- <input type="button" value="测试" οnclick="testf()" ?/> -->
</body>
?
<script type="text/javascript">
 ? ?//demo07面试题:请问bind,call,apply的区别
 ? ?//1、相同点:
 ? ?// ? 三个函数都会改变this的指向(调用这三个函数的函数内部的this)
?
?
 ? ?//2、不同点:
 ? ?//  1)、bind会产生新的函数,(把对象和函数绑定死后,产生新的函数)
 ? ?//  2)、call和apply不会产生新的函数,只是在调用时,绑定一下而已。
 ? ?//  3)、call和apply的区别,第一个参数都是要绑定的this,apply第二个参数是数组(是函数的所有参数),call把apply的第二个参数单列出来。
?
 ? ?//示例代码:
 ? ?var p1 = {
 ? ? ? ?name:"隔壁老王",
 ?  }
?
 ? ?function eat(str,drinkstr) {
 ? ? ? ?console.log(this.name+"在吃"+str+",同时在喝"+drinkstr);
 ?  }
?
 ? ?//1、bind:
 ? ?let f1 = eat.bind(p1);//f1是个函数。即,用bind把eat函数和p1对象绑死,产生新的函数叫作f1
 ? ?f1("油条","豆浆");//调用f1,就相当于 p1.eat();,内部的this就是p1,永远都是p1,不会是window
?
 ? ?//2、call:
 ? ?eat.call(p1,"油泼面","面汤");//不会产生新的函数,只是临时把eat函数和p1对象绑定一下。
?
 ? ?//3、apply:(与call的意思一样,只是第二个参数是数组,是原函数eat的参数)
 ? ?eat.apply(p1,["油泼面","面汤"]);//不会产生新的函数,只是临时把eat函数和p1对象绑定一下。
?
</script>

13、构造函数和普通函数的区别(面试题):

1)、函数名的首字母大写

2)、构造函数的调用,是用new运算符。

3)、构造函数内部,在预编译时,还会增加 var this = new Object();

4)、构造函数(看上去)没有返回值,但是,其实是有的。即:虽然程序员没有写返回值,预编译时,会增加返回值

预编译时,会增加一句:return this。

14、构造函数的执行过程(面试时有时会问):

1、立刻在堆内存中申请空间,这个空间就是新的对象的内存空间

2、将新建的对象设置为函数中的this

3、逐个执行函数中的代码

4、将新建的对象作为返回值 return this

15、原型和原型链

1、原型:

1)、每个构造函数(类)都会有一个原型属性(prototype)。

2)、原型属性的目的:

让所有实例共享属性和方法,共享的是构造函数(类)的原型属性(prototype)上的属性和方法。因此,节约了内存。实例是通过 __proto__属性找到构造函数(类)的prototype属性的。

3)、原型属性里还有一个constructor属性,指向构造函数(类)本身。

2、原型链

当使用对象访问属性或者方法时,先从对象本身的内存中寻找,如果找不到,就去 __proto__(原型)指向的内存中(类的prototype)寻找,如果找不到,则在类的原型的 __proto__(父类的prototype)寻找,以此类推,一直找到Object,如果没有找到,则显示出错(如: *** is not defined)。

这种一直沿着属性 __proto__ 朝上寻找,就是原型链的寻找。也就是原型链的意思。

文章来源:https://blog.csdn.net/jiang7701037/article/details/135789702
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。