概述
前端面试拾遗——this、类型检测、es6
前言
上一篇文章主要讲了我到某公司面试前端岗位时跟CSS有关的部分,这一篇文章将会总结一下面试过程中跟JS有关的部分,JS部分面试官主要问到了JS的类型以及ES6新增的类型,如何改变函数中this指针的指向,以及说一下平常使用过的ES6新特性。下面会有我面试后查阅资料后的相关解答。
this相关
关于this的详细介绍可以查看 MDN this 。在谈如何改变函数中this的指向时,我们先来谈一下this指向的究竟是什么。在传统的面向对象语言中,this指向的就是对象本身,那么JS是不是也一样呢?首先我们先执行下面的代码
function getThis() {
console.log(this)
}
getThis(); //Window
var ObjectB = {
getThis: getThis
}
ObjectB.getThis() //Object
var getThisA = ObjectB.getThis
getThisA() //Object
输出结果如下所示
如果this指向的是对象本身的话,那么三个输出应该是一样的,而在这里我们可以看到三个输出并不是完全相同。其实在JS中this指向的是执行上下文,什么是执行上下文呢,通俗来说也就是执行这个函数的对象。像第一次执行执行的对象是全局Window,而第二次执行是ObjectB,第三次执行也是全局Window。根据这个原理,我们只要改变执行函数的对象就能改变this的指向。执行函数的方式有以下方式:
- 直接调用
- 作为对象的方法调用
- call和apply方法
- bind方法
- 还有一个不太确定的就是箭头函数
直接调用和作为对象方法调用改变this指向在上个例子已经展示出来了,接下来着重介绍call、apply和bind方法,为何方便辨识对象下面定义类都使用构造函数的方法定义。
测试代码如下
var getThis = function() {
console.log(this)
}
function ObjectA() {}
objectA = new ObjectA()
// 直接执行时getThis的this指向
console.log("直接执行时getThis的this指向")
getThis()
// call方法改变getThis中this的指向
console.log("call方法改变getThis中this的指向")
getThis.call(objectA)
// apply方法改变getThis中this的指向
console.log("apply方法改变getThis中this的指向")
getThis.apply(objectA)
// bind方法改变getThis中this的指向
console.log("bind方法改变getThis中this的指向")
var newGetThis = getThis.bind(objectA)
newGetThis()
执行结果如下所示
可以看出通过call,apply和bind方法可以轻松改变函数中this的指向。
还有就是箭头函数,相对与普通函数来说,箭头函数this的指向一定是声明他的对象,那么相对与普通函数来说,应该改变的却没有改变,那究竟算不算改变了指向呢?如果是面试的话可以跟面试官讨论一下,就从我的面试来说,面试官是不同一箭头函数改变this指向这种说法的。箭头函数跟普通函数this指向的测试如下
var ObjectA = function() {
this.getThis = () => {
console.log(this)
}
this.otherGetThis = function() {
console.log(this)
}
}
var objectA = new ObjectA()
var getThis = objectA.getThis
console.log("箭头函数this指向")
getThis()
var otherGetThis = objectA.otherGetThis
console.log("普通函数this指向")
otherGetThis()
运行结果如下
可以看到箭头函数的指向是没有改变的还是指向ObjectA而普通函数this指向了调用它的全局Window
类型检测
在面试过程中,面试官有问到关于JS类型检测的问题,之前也没有考虑过这个问题,就答了一个 instanceof
运算符,然后面试官接着就问除了 instanceof
呢或者是 instanceof
有什么缺陷。当时就没想起来,其实在JS中有 instanceof
和 typeof
两个关于类型检测的运算符,在《JavaScript高级程序设计》中有这种说法:当检测的是基础类型的时候使用 typeof
更好,而当检测的是引用类型的时候使用 instanceof
更好。为什么会有这种说法呢,我们可以看一下测试代码
var ObjectA = function() {}
var objectA = new ObjectA()
console.log("获取objectA的类型")
console.log(typeof objectA)
console.log("判断objectA是否为Object的引用")
console.log(objectA instanceof Object)
console.log("判断objectA是否为ObjectA的引用")
console.log(objectA instanceof ObjectA)
var num = 1
console.log("判断num的类型")
console.log(typeof num)
console.log("判断num是否为Number的引用")
console.log(num instanceof Number)
num = new Number(1)
console.log("判断重新赋值的num的类型")
console.log(typeof num)
console.log("判断重新赋值的num是否为Number的引用")
console.log(num instanceof Number)
输出的结果如图所示
我们可以看到使用 typeof
运算精度只能是基础类型也就是 number
, string
, undefined
, boolean
, object
,要注意的是 null
和数组使用 typeof
运算符得到的也是 object
而 instanceof
运算符可以精确到是哪一种类型的引用例如测试程序中的ObjectA
,但 instanceof
也有一个缺陷就是对于直接赋值的数字,字符串,布尔值以及数组是不能将其识别为Number
,String
,Boolean
,Array
。这时候怎么将两者的优势结合起来让直接赋值的数字,字符串,布尔值和数组能直接获取到正确的类型呢?我主要是从loadash的源码中获取灵感的,我们可以使用Symbol.toStringTag
的方法获取各种类型的tag,其中Number
类型的tag为[object,Number]
,以此类推。而自定义的属性可一通过重写get[Symbol.toStringTag]
来自定义tag,测试的代码入下
class ObjectA {
get [Symbol.toStringTag]() {
return "ObjectA";
}
}
var objectA = new ObjectA()
console.log("获取自定义类型的类型")
console.log(Object.prototype.toString.call(objectA))
var num = 1
console.log("获取普通类型的对应的类型")
console.log(Object.prototype.toString.call(num))
num = new Number(1)
console.log("获取引用类型的类型")
console.log(Object.prototype.toString.call(num))
运行结果如下图所示
通过这种方法无论是直接赋值还是构造函数赋值,无论是内置类型还是自定义类型都能够识别,相对来说是比较通用的解决办法。
es6
我觉得现在前端的面试是肯定会问到的,所以在面试前特意复习了一下,然而到了面试的时候面试官问的关于es6的东西几乎都没有答上。面试官主要问了两个问题,es6新增了哪些数据类型;你使用过es6哪些新特性。
es6仅仅新增了一个数据类型那就是Symbol,关于Symbol的详细介绍可以参考 阮一峰的es6入门教程 。
至于es6的新特性那就多了,在这里列出常用的几种,数据解构,class,promise,构造器,Proxy,Reflect,箭头函数。
es6要展开写实在太多东西写了,所以就只给出了链接,方便以后查阅。
总结
这篇文章主要是总结了面试过程中面试官问到的关于JS语言层面的知识点,通过查阅资料后给出的解答。
最后
以上就是呆萌小虾米为你收集整理的前端面试拾遗——this、类型检测、es6前端面试拾遗——this、类型检测、es6的全部内容,希望文章能够帮你解决前端面试拾遗——this、类型检测、es6前端面试拾遗——this、类型检测、es6所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复