一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
1、js有哪些数据类型?
js有8种数据类型,分别是undefined,null,Boolean,number,string,object,symbol,bigint
栈:原始数据类型(undefined,null,boolean,number,string)
堆:引用数据类型(对象、数组、函数)
1、原始数据类型直接存储在栈(stack)中的简单数据段,占据空间大,属于被频繁使用的数据,所以放入栈中存储。
2、引用数据类型存储在堆(heap) 中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。举个例子: 我这边有- -篇作文内容上干字,作文内容比较多就是放在堆里面管理的,作文标题(这个对象的变量引用)放在栈区里面,当点击作文标题的时候,会通过当前的地址关联到堆区里面的作文详情页。
2、数据类型检测的方式有哪些?
1、typeof
(1)只能判断原始值(number,string这些等等),判断引用类型(array,object,null)这些结果都是object,判断不了
2、instanceof
(1)判断不了原始值(number,string这些等等),可以判断引用类型(array,object,null)
(2)其内部运行机制是判断在其原型链中能否找到该类型的原型,因此这块要研究下如何手写instanceof方法,面试官很可能问到,后面手写篇会讲到这块手写写法
3、Object.prototype.toString.call()
3、判断数组的方式有哪些?
1、Object.prototype.toString.call()
2、通过原型链做判断 obj.__proto__===Array.prototype
3、Array.isArray()
4、instanceof
4、null和undefined的区别?
相同点:都是原始数据类型
不同点:使用typeof进行判断时,Null类型会返回Object;使用双等号对两种类型的值进行比较时,会返回true,三个等号会返回false
5、typeof null的结果是什么?
结果是object
6、instanceof操作符的实现原理及实现?
instanceof用于判断构造函数的prototype属性是否出现在对象的原型链中。
所以我们一般这么来实现:比如我这边有个自定义的myInstanceof方法,这个方法的形参第一个是对象实例,第二个是构造函数。会先通过Object.getPrototypeOf(对象实例)拿到对象原型,在通过第二个形参的prototype拿到构造函数的对象。通过while循环来判断这两个对象是否相等,如果不相等一直获取这个对象的__proto__来比较,直到找到相等就返回true。如果一直递归到最顶级也没找到(object),那就会返回false。
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)
}
}
7、new操作符的实现原理?
1、首先创建了一个新的空对象
2、设置原型,将对象的原型设置为函数的prototype对象
3、让函数的this指向这个对象,执行构造函数的代码(为这个新对象添加属性)
4、判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象
具体实现:
function objectFactory(){
let newObject = null
let constructor = Array.prototype.shift.call(arguments)
let result = null
//判断参数是否是一个函数
if(typeof constructor !== "function"){
console.error("type error");
return
}
//新建一个空对象,对象的原型为构造函数的prototype对象
newObject=Object.create(constructor.prototype)
//将this指向新建对象,并执行函数
result= constructor.apply(newObject,arguments)
// 判断返回对象
let flag = result && (typeof result ==="object" || typeof result==="function")
// 判断返回结果
return flag ? result : newObject
}
//使用方法
objectFactory(构造函数,初始化函数)
8、数组有哪些原生方法?
1、数组和字符串的转换方法:toString()、toLocalString()、join() 其中的join()方法可以指定转换为字符串的分隔符
2、数组尾部操作的方法pop()和push(),push方法可以传入多个参数
3、数组首部操作的方法shift()、unshift()重排序的方法reverse()和sort(),sort()方法可以传入一个函数来进行比较,传入前后两个值,如果返回值是正数,则交换两个参数的位置
4、数组连接的方法concat(),返回的是拼接好的数组,不影响原数组
5、数组截取方法slice(),用于截取数组中的一部分返回,不影响原数组
6、数组归并方法reduce()和reduceRight()方法
9、什么是Dom和Bom?
DOM全称:Document object model 指的是文档对象模型
BOM全称:Bowser object model 指的是浏览器对象模型
BOM的核心是window,而window对象具有双重角色,它即是通过js访问浏览器窗口的一个接口,有事也该Global(全局)对象。
window对象含有location对象、navigator对象、screen对象等子对象,并且DOM的最根本的对象document对象也是BOM的window对象的子对象。
10、对类数组对象的理解,如何转换后为数组?
一个拥有length属性和若干索引属性(从零开始递增)的对象就可以被称为类数组对象,类数组对象和数组类似,但是不能调用数组的方法。举个例子:函数参数也可以看做是类数组
常见的类数组转换为数组的方法有这样几种:
1、通过call调用数组的slice方法来实现转换
Array.prototype.slice.call(arrayLike)
2、通过call调用数组的splice方法来实现转换
Array.prototype.splice.call(arrayLike,0)
3、通过apply调用数组的concat方法来实现转换
Array.prototype.concat.apply([],arrayLike)
4、通过Array.from方法来实现转换
Array.from(arrayLike)