前端 JS 面试题

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

基本类型:

Number、String、Boolean、Undefined、null、symbol

引用类型:

Object、Array、Function

基本数据类型和引用数据类型存储在内存中的位置不同:

  • 基本数据类型存储在栈中

  • 引用类型的对象存储于堆中

  • 声明变量时不同的内存地址分配:

    • 简单类型的值存放在栈中,在栈中存放的是对应的值

    • 引用类型对应的值存储在堆中,在栈中存放的是指向堆内存的地址

  • 不同的类型数据导致赋值变量时的不同:

    • 简单类型赋值,是生成相同的值,两个对象对应不同的地址

    • 复杂类型赋值,是将保存对象的内存地址赋值给另一个变量。也就是两个变量指向堆内存中同一个对象

2 == 和 ===区别,分别在什么情况使用?

等于操作符(==)在比较中会先进行类型转换,再确定操作数是否相等

  • 两个都为简单类型,字符串和布尔值都会转换成数值,再比较

  • 简单类型与引用类型比较,对象转化成其原始类型的值,再比较

  • 两个都为引用类型,则比较它们是否指向同一个对象

  • null 和 undefined 相等

  • 存在 NaN 则返回 false

全等操作符由 3 个等于号( === )表示,只有两个操作数在不转换的前提下相等才返回 true。即类型相同,值也需相同

nullundefined 比较,相等操作符(==)为true,全等为false

3 typeof 与 instanceof 区别?

  • typeof用于判断数据类型,返回值为以下7种类型

    • 数字类型、typeof 返回的值是 number。比如说:typeof(1),返回值是 number

    • 字符串类型,typeof 返回的值是 string。比如 typeof(“123”返回值时 string)

    • 布尔类型,typeof 返回的值是 boolean。比如 typeof(true)返回值时 boolean

    • 对象、数组、null 返回的值是 object。比如 typeof(window),typeof(document),typeof(null)返回 的值都是 object;使用 typeof 运算符无论引用的是什么类型的对象,它都返回”object”

    • 函数类型,返回的值是 function。比如:typeof(eval),typeof(Date)返回的值都是 function。

    • 不存在的变量、函数或者 undefined,将返回 undefined。比如:typeof(abc)、typeof(undefined) 都返回 undefined

  • instanceof 只能判断对象类型,用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上,通俗地讲:用来检测某个对象是谁的实例

如果需要通用检测数据类型,可以采用Object.prototype.toString,调用该方法,统一返回格式“[object Xxx]”的字符串

4 深拷贝浅拷贝的区别?如何实现一个深拷贝?

浅拷贝

浅拷贝,指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝

如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址

即浅拷贝是拷贝一层,深层次的引用类型则共享内存地址

在JavaScript中,存在浅拷贝的现象有:

  • Object.assign

  • Array.prototype.slice(),, Array.prototype.concat()

  • 使用拓展运算符实现的复制

深拷贝

深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性

常见的深拷贝方式有:

  • _.cloneDeep()

  • jQuery.extend()

  • JSON.stringify()

  • 手写循环递归

前提为拷贝类型为引用类型的情况下:

浅拷贝是拷贝一层,属性为对象时,浅拷贝是复制,两个对象指向同一个地址

深拷贝是递归拷贝深层次,属性为对象时,深拷贝是新开栈,两个对象指向不同的地址

5 说说你对作用域链的理解?

作用域:

作用域,即变量(变量作用域又称上下文)和函数生效(能被访问)的区域或集合

  • 全局作用域:任何不在函数中或是大括号中声明的变量,都是在全局作用域下,全局作用域下声明的变量可以在程序的任意位置访问

  • 函数作用域:函数作用域也叫局部作用域,如果一个变量是在函数内部声明的它就在一个函数作用域下面。这些变量只能在函数内部访问,不能在函数以外去访问

  • 块级作用域:ES6引入了let和const关键字,和var关键字不同,在大括号中使用let和const声明的变量存在于块级作用域中。在大括号之外不能访问这些变量

作用域链:在js中,有全局作用域和局部作用域两种作用域,作用域链就是里层的作用域可以使用外层作用域的变量和数据等等,但是外层不能使用里层作用域的变量和方法等等,不同作用域,并且这两个作用之间不是父子的关系,那么这两个作用域里面的数据也是不互通的

6 箭头函数?

箭头函数不会创建自己的this,它只会从自己的作用域链的上一层沿用this

只有一个参数可以省略小括号;

如果函数体只有一行代码,可以写到一行上,并且无需写 return 直接返回值;

如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回;

加括号的函数体返回对象字面量表达式

7 JavaScript原型,原型链?

原型:所有的函数都有一个特殊的属性prototype(原型),prototype属性是一个指针,指向的是一个对象(原型对象),原型对象中的方法和属性都可以被函数的实例所共享。所谓的函数实例是指以函数作为构造函数创建的对象,这些对象实例都可以共享构造函数的原型的方法。

原型链:

  • 访问一个对象的属性时,会先在这个对象的属性上进行查找,

  • 如果没有就会通过它实例对象的proto去它构造函数的原型prototype上去查找,

  • 如果还没有,就通过原型对象的proto去查找,

  • 这样一层一层的去查找就是原型链,如果一直没有找到最后会找到Object的原型上,最终返回的就是null。

作用域链:

JavaScript 在执⾏过程中会创建一个个的可执⾏上下⽂。 (每个函数执行都会创建这么一个可执行上下文)每个可执⾏上下⽂的词法环境中包含了对外部词法环境的引⽤,可通过该引⽤来获取外部词法环境中的变量和声明等。这些引⽤串联起来,⼀直指向全局的词法环境,形成一个链式结构,被称为作⽤域链。

简而言之:函数内部 可以访问到 函数外部作用域的变量, 而外部函数还可以访问到全局作用域的变量,这样的变量作用域访问的链式结构, 被称之为作用域链;

原型链与作用域链区别:

  • 作用域是对于变量而言,原型链是对于对象的属性。

  • 作用域链顶层是window,原型链顶层是Object。

  • 联系:从链表开头寻找,直到找到为止。

8 说说你对闭包的理解?闭包使用场景?

闭包让你可以在一个内层函数中访问到其外层函数的作用域

任何闭包的使用场景都离不开这两点:

  • 创建私有变量

  • 延长变量的生命周期

9 说说 JavaScript 中内存泄漏的几种情况

内存泄漏:程序中己动态分配的堆内存由于某种原因未释放或无法释放。

内存泄露的几种场景:

  • 全局变量过多

  • 闭包

  • 事件监听未被移除

  • 缓存

两种常见的垃圾回收算法有:引用计数法和标记清除法。

  • 引用计数法就是:记录每个值被引用的次数,如果值被用了一次就记录1,多次引用就继续累加。少一次引用就减1,如果引用次数是0,就会释放内存。但是他有一个问题就是嵌套引用他无法清除。

  • 标记清除法:标记清除算法将“不再使用的对象”定义为“无法达到的对象”;就是从根部(在JS中就是全局对象)出发定时扫描内存中的对象,凡是能从根部到达的对象,都是还需要使用的;那些无法由根部出发触及到的对象被标记为不再使用,稍后进行回收。

10 call、apply和bind区别:

相同点:作用相同,都是动态修改this指向;都不会修改原先函数的this指向

不同点:

  • 执行方式不同:

    • call和apply是改变后页面加载之后就立即执行,是同步代码。

    • bind是异步代码,改变后不会立即执行;而是返回一个新的函数。

  • 传参方式不同:

    • call和bind传参是一个一个逐一传入,不能使用剩余参数的方式传参。

    • apply可以使用数组的方式传入的,只要是数组方式就可以使用剩余参数的方式传入。

11 Javascript如何实现继承?

使用Object.create:

  • 原型式继承

  • 寄生式继承

  • 二者组合为寄生组合继承

不使用Object.create:

  • 原型链继承

  • 构造函数继承(借助 call)

  • 二者组合为组合继承

12 说说new操作符具体干了什么?

  • 首先创建了一个新的空对象 newObject:

  • 利用Object.create(),将我们上一步拿到的构造函数的prototype指向了新创建的对象newObject

  • 通过apply()改变了this指向,让函数的 this 指向这个新创建的空对象,执行构造函数的代码。为新创建的空对象添加属性。

  • 判断调用函数过后的返回值类型,如果是基本数据类型,则返回创建的对象。如果是引用类型,就返回这个引用类型的对象。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值