JS面试

一、数据类型

1、JavaScript有哪些数据类型,它们的区别?

1.1、类型:基本、引用

1.2、两种类型的区别在于存储位置的不同

基本数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;

引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体

2、类型检测

基本类型:typeof xxx

引用类型:xxx instanceof constructor

所有 通用:Object.prototype.toString.call()

3、object.assign和扩展运算法 都是浅拷贝 

4、如何判断一个对象是空对象

使用JSON自带的JSON.stringify == '{}' 方法来判断

使用ES6新增的方法Object.keys(obj).length 来判断

二、ES6

1、如果new一个箭头函数的会怎么样

箭头函数是ES6中的提出来的,它没有prototype,也没有自己的this指向,更不可以使用arguments参数,所以不能New一个箭头函数;

  new操作符的实现步骤如下:

  1. 创建一个对象

  2. 将构造函数的作用域赋给新对象(也就是将对象的__proto__属性指向构造函数的prototype属性)

  3. 指向构造函数中的代码,构造函数中的this指向该对象(也就是为这个对象添加属性和方法)

  4. 返回新的对象                

所以,上面的第二、三步,箭头函数都是没有办法执行的。

 

2、箭头函数的this指向哪里?

箭头函数不同于传统JavaScript中的函数,箭头函数并没有属于⾃⼰的this,它所谓的this是捕获其所在上下⽂的 this 值,作为自己的 this 值,并且由于没有属于自己的this,所以是不会被new调⽤的,这个所谓的this也不会被改变。箭头函数的this指向外层函数的this

三、JS基础

1、Map与Object 

1.1、Object不是 iterable,不可以被迭代,不能用for...of遍历,map可以

1.2、键的类型

Map的键可以是任意值,包括函数、对象或任意基本类型。
Object 的键必须是 String 或是Symbol。

1.3、键的顺序

Map 中的 key 是有序的。因此,当迭代的时候, Map 对象以插入的顺序返回键值。
Object 的键是无序的

2、为什么函数的 arguments 参数是类数组而不是数组?如何遍历类数组?

2.1、arguments是一个对象,它的属性是从 0 开始依次递增的数字,还有callee和length等属性,与数组相似;但是它却没有数组常见的方法属性,如forEach, reduce等,所以叫它们类数组。
2.2、要遍历类数组的方法
a、使用call和apply方法

b、Array.from方法将类数组转化成数组

c、使用展开运算符将类数组转化成数组

3、ES6模块与CommonJS模块有什么异同?

不同点
1.CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
2.CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载
3.CommonJS是对模块的浅拷贝,ES6 Module是对模块的引入,即ES6 Module只存只读,不能改变其值,具体点就是指针指向不能变,类似const 。
4.import的接口是read-only(只读状态),不能修改其变量值。 即不能修改其变量的指针指向,但可以改变变量内部指针指向。可以对commonJS重新赋值(改变指针指向),但是对ES6 Module赋值会编译报错。
相同点
CommonJS和ES6 Module都可以对引⼊的对象进⾏赋值,即对对象内部属性的值进⾏改变

4、for...in和for...of的区别

区别
for… in 会遍历对象的整个原型链,性能非常差不推荐使用,而 for … of 只遍历当前对象不会遍历原型链
对于数组的遍历,for…in 会返回数组中所有可枚举的属性(包括原型链上可枚举的属性),for…of 只返回数组的下标对应的属性值

5、如何实现深拷贝?

5.1、JSON.stringify()
● JSON.parse(JSON.stringify(obj))是目前比较常用的深拷贝方法之一,它的原理就是利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象。
● 这个方法可以简单粗暴的实现深拷贝,但是还存在问题,拷贝的对象中如果有函数,undefined,symbol,当使用过JSON.stringify()进行处理之后,都会消失。

5.2、函数库lodash的_.cloneDeep方法

5.3、手写实现深拷贝函数

 

四、原型

1、对原型、原型链的理解

在JavaScript中是使用构造函数来初始化一个对象的,每一个构造函数的内部都有一个 prototype(原型对象) 属性,它的属性值是一个对象,这个对象包含了可以由该构造函数的所有实例共享的属性和方法。当使用构造函数新建一个对象后,在这个对象的内部将包含一个指针,这个指针指向构造函数的 prototype 属性对应的值,在 ES5 中这个指针被称为对象的原型。一般来说不应该能够获取到这个值的,但是现在浏览器中都实现了 __proto__ 属性来访问这个属性(prototype原型对象),但是最好不要使用这个属性,因为它不是规范中规定的。ES5 中新增了一个 Object.getPrototypeOf() 方法,可以通过这个方法来获取对象的原型。当访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念。原型链的尽头一般来说都是 Object.prototype(除null外)

 

 2、原型修改、重写

修改:并没有改变构造函数原型对象内部的constructor指向,只是在原型对象身上新增了属性或者方法

重写:将构造函数的原型对象直接进行替换,修改了构造函数内部constructor的指向,若想仍然指向原来的构造函数,需要在修改的原型对象内部重新将constructor指向该构造函数
3、
原型链指向

4、原型链的终点是什么?如何打印出原型链的终点?

原型链的终点
由于Object是构造函数,原型链终点是Object.prototype.__proto__,而Object.prototype.__proto__=== null // true,所以,原型链的终点是null
如何打印出原型链的终点
原型链上的所有原型都是对象,所有的对象最终都是由Object构造的,而Object.prototype的下一级是Object.prototype.__proto__

5、如何获得对象非原型链上的属性?

使用hasOwnProperty()方法来判断属性是否属于原型链的属性

 

posted on 2022-08-31 16:08  二月龙抬头之伏龙翔天  阅读(63)  评论(0)    收藏  举报

导航