前端面试拾遗——this、类型检测、es6

前端面试拾遗——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() //Window

输出结果如下所示

this输出结果

如果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()

执行结果如下所示

callapplybind改变this指向

可以看出通过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()

运行结果如下

箭头函数与普通函数this指向测试

可以看到箭头函数的指向是没有改变的还是指向ObjectA而普通函数this指向了调用它的全局Window

类型检测

 在面试过程中,面试官有问到关于JS类型检测的问题,之前也没有考虑过这个问题,就答了一个 instanceof 运算符,然后面试官接着就问除了 instanceof 呢或者是 instanceof 有什么缺陷。当时就没想起来,其实在JS中有 instanceoftypeof 两个关于类型检测的运算符,在《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 运算精度只能是基础类型也就是 numberstringundefinedbooleanobject ,要注意的是 null 和数组使用 typeof 运算符得到的也是 objectinstanceof 运算符可以精确到是哪一种类型的引用例如测试程序中的ObjectA,但 instanceof 也有一个缺陷就是对于直接赋值的数字,字符串,布尔值以及数组是不能将其识别为NumberStringBooleanArray。这时候怎么将两者的优势结合起来让直接赋值的数字,字符串,布尔值和数组能直接获取到正确的类型呢?我主要是从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))

运行结果如下图所示

Symbol类型判别

通过这种方法无论是直接赋值还是构造函数赋值,无论是内置类型还是自定义类型都能够识别,相对来说是比较通用的解决办法。

es6

 我觉得现在前端的面试是肯定会问到的,所以在面试前特意复习了一下,然而到了面试的时候面试官问的关于es6的东西几乎都没有答上。面试官主要问了两个问题,es6新增了哪些数据类型;你使用过es6哪些新特性。
es6仅仅新增了一个数据类型那就是Symbol,关于Symbol的详细介绍可以参考 阮一峰的es6入门教程
至于es6的新特性那就多了,在这里列出常用的几种,数据解构classpromise构造器ProxyReflect箭头函数
es6要展开写实在太多东西写了,所以就只给出了链接,方便以后查阅。

#前端工程师#
全部评论
有一个错误,数组直接赋值的话,用instanceof也能检查出是Array类型的。数字,字符串,布尔值的直接赋值才不能用instanceof检测出是Number String Boolean而已。
点赞
送花
回复
分享
发布于 2017-09-27 10:20

相关推荐

点赞 53 评论
分享
牛客网
牛客企业服务