New
在JS基础面试题中,我们经常都能遇到new的相关问题,但是较多从事前端行业不久的同学们却总是希望通过背题这种方式来逃过面试官的法眼,回答问题的时候也胆战心惊生怕面试官逮住问题继续深究。
好,正题。众所周知,
new关键字后面接的是函数(除了箭头函数外其他函数皆可),会执行函数内的代码,返回值是一个对象,如果没有return或者return值并不是一个对象的话,则会返回一个实例,该实例由函数内部this属性值和_proto_
构成。_proto_
本身内容不再赘述,具体参照原型链相关文章。
上面两段代码都不难理解,bObj是通过B这个构造函数生成的一个实例,B上面有一个参数,通过向构造函数传参的方式可以更加自由地创建实例,那么new在这期间执行了一个什么样的过程呢?
- 创建一个空对象
- 将函数内部的this指向上一步新建的空对象
- 执行函数内部的代码
- 将新建的对象的
_proto_
属性指向函数的prototype - 返回新对象或者用户自定义的对象
由此可以进一步总结:
- 让实例可以访问到私有属性
- 让实例可以访问构造函数原型所在原型链上的属性
- 构造函数返回的最后结果是引用数据类型
下面我们来模仿一下new关键字的实现代码
apply、call And bind介绍
三者都是挂载到Function对象上的方法,故调用这三个方法的必须是一个函数。在使用区别上,三者的方法是两两相同又两两不同,除了bind是返回一个函数,其他都是立即调用。
下面是三个方法的使用示例:
其中 func 是要调用的函数,thisArg 一般为 this 所指向的对象,后面的 param1、2 为函数 func 的多个参数,如果 func 不需要参数,则后面的 param1、2 可以不写。
这三个方法共有的、比较明显的作用就是,都可以改变函数 func 的 this 指向。call 和 apply 的区别在于,传参的写法不同:apply 的第 2 个参数为数组; call 则是从第 2 个至第 N 个都是给 func 的传参;而 bind 和这两个(call、apply)又不同,bind 虽然改变了 func 的 this 指向,但不是马上执行,而这两个(call、apply)是在改变了函数的 this 指向之后立马执行。
这几个方法的区别和原理基本讲清楚了,但是理解起来是不是很抽象呢?那么我举个形象的例子再配合着代码一起看下。
例如,生活中我不经常做饭,家里没有锅,周末突然想给自己做个饭尝尝。但是家里没有锅,而我又不想出去买,所以就问隔壁邻居借了一个锅来用,这样做了饭,又节省了开销,一举两得。
对应在程序中:A 对象有个 getName 的方法,B 对象也需要临时使用同样的方法,那么这时候我们是单独为 B 对象扩展一个方法,还是借用一下 A 对象的方法呢?当然是可以借用 A 对象的 getName 方法,既达到了目的,又节省重复定义,节约内存空间。
为了更好地掌握这部分概念,我们结合一段代码再深入理解一下这几个方法。
从上面的代码执行的结果中可以发现,使用这三种方式都可以达成我们想要的目标,即通过改变 this 的指向,让 b 对象可以直接使用 a 对象中的 getName 方法。从结果中可以看到,最后三个方法输出的都是和 lily 相关的打印结果,满足了我们的预期。
我们再看看这几个方法的使用场景。
-
判断数据类型
用 Object.prototype.toString 来判断类型是最合适的,借用它我们几乎可以判断所有类型的数据。
-
类数组借用方法
类数组因为不是真正的数组,所有没有数组类型上自带的种种方法,所以我们就可以利用一些方法去借用数组的方法,比如借用数组的 push 方法,看下面的一段代码。
-
获取数组的最大 / 最小值
我们可以用 apply 来实现数组中判断最大 / 最小值,apply 直接传递数组作为调用方法的参数,也可以减少一步展开数组,可以直接使用 Math.max、Math.min 来获取数组的最大值 / 最小值,请看下面这段代码。
-
继承
call代码实现
apply代码实现
apply与call大同小异,唯一的区别就是后面的参数传递形式不同
bind代码实现
bind与call也基本一致,不一样的是bind返回一个函数,并不立即执行
总结
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!