前端常见面试题1

JS相关

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

typeof:对于基本数据类型判断是没有问题,但遇到引用数据类型有问题。当变量是:number, string, boolean, function, undefined, object类型时,可以使用typeof进行判断。当变量是array, json, null, date, reg(正则), error 类型时全部被错误的检测为object类型。

instanceof:基本数据类型会有问题,而引用数据类型没有问题 可以在继承关系中用来判断一个实例是否属于它的父类型 判断 new 关键字创建的引用数据类型不考虑 null 和 undefined(这两个比较特殊)以对象字面量创建的基本数据类型。

constructor: constructor 似乎完全可以应对基本数据类型和引用数据类型 但如果声明了一个构造函数,并且把他的原型指向了Array的原型 constructor 也显得力不从心。
原因:

1、array属于引用型数据,在传递过程中,仅仅是引用地址的传递。
2、每个页面的Array原生对象 所引用的地址是不一样的,在子页面声明的array,所对应的构造函数,是子页面的Array对象;父页面来进行判断,使用的Array并不等于子页面的Array;切记,不然很难跟踪问题!
解决:Object.prototype.toString.call()

2、深拷贝和浅拷贝

深拷贝和浅拷贝是针对复杂数据类型来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝。

浅拷贝:浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,当引用指向的值改变时也会跟着变化。

深拷贝:深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。 深拷贝后的对象与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。

浅拷贝:(只能拷贝一层):Object.assign和for in进行{ }和[ ]的拷贝。

深拷贝最简单的实现是:JSON.parse ( JSON.stringify ( obj ) ),同时有一定的缺陷:
也可以利用数组的Array.prototype.forEach进copy

  • 拷贝的对象的值中如果有函数,undefined,symbol则经过JSON.stringify()序列化后的JSON字符串中这个键值对会消失
  • 无法拷贝不可枚举的属性,无法拷贝对象的原型链
  • 拷贝Date引用类型会变成字符串
  • 拷贝RegExp引用类型会变成空对象
  • 对象中含有NaN、Infinity和-Infinity,则序列化的结果会变成null
  • 无法拷贝对象的循环应用(即obj[key] = obj)

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

arguments:是一个类似于数组的对象,对应于传递给函数的参数,他有length属性,可以arguments[ i ]来访问对象中的元素,但是它不能用数组的一些方法。例如push、pop、slice等。arguments虽然不是一个数组,但是它可以转成一个真正的数组。
注意:arguments有length属性可以使用splice
转换数组:

  • 1.var args = [].slice.call(arguments); //第一种
  • 2.var args = Array.prototype.slice.call(arguments); //第二种
  • 3.let args = Array.from(arguments); //第三种
  • 4.let args = [...arguments]; //第四种

4、作用域链、闭包、作用域

⑴ 作用域链 定义:一个函数在访问变量的时候,优先使用自己的局部变量,如果没有这个变量的申明,则向上级访问,一直访问到全局。全局都没有的话,语法错误:is not defined。

⑵闭包closure 定义:当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数的内部变量,且返回的那个函数在外部被执行,就产生了闭包.闭包是一个环境,具体指的就是外部函数--高阶函数

闭包的特性: ①函数嵌套函数;
②内部函数可以直接访问外部函数的内部变量或参数;
③变量或参数不会被垃圾回收机制回收。
闭包的优点:
①变量长期驻扎在内存中;
②避免全局变量的污染;
③私有成员的存在。
闭包的缺点:

  • 常驻内存
  • 增大内存的使用量 使用不当会造成内存泄
  • 作用域:全局作用域:window。
  • 局部作用域:函数内部定义的。

5、js数组常见的方法

1.push在数组末尾添加一个或多个元素,并返回数组的长度, 可以添加任意类型的值作为数组的一个元素。
2.unshift 在最前面添加一个或多个元素,并返回数组的长度,可以添加任意类型的值作为数组的一个元素。
3.pop 删除最后一个元素,并返回删除元素的值;如果数组为空则返回undefine。该方法会改变原始数组
4.shift 删除数组第一个元素,并返回被删除的元素;如果数组为空则返回undefine。该方法会改变原始数组
5.slice截取数组,得到截取的数组;不改变原始数组,得到新的数组.
6.splice剪接数组,向/从数组中添加/删除项目,然后返回被删除的项目,该方法会改变原始数组,索引从0开始
7.concat 合并两个或多个数组,得到新数组,原始数组不改变,如果要进行concat()操作的参数是数组,那么添加的是数组中的元素,而不是数组。
8.indexOf 数组元素索引,并返回元素索引,不存在返回-1,索引从0开始
9.join 数组转字符串,与toString()方法类似
10.reverse 颠倒数组中元素的顺序,该方法会改变原来的数组,而不会创建新的数组。 11.fill() 方法用于将一个固定值替换数组的元素。("要填充的值",开始位置,结束位置)

原文地址:https://www.cnblogs.com/mxnl/p/13694007.html