明确函数的双重作用(Clarifying the Dual Purpose of Functions)

在ES5及更早的ES版本中,函数调用时是否使用new会有不同的作用。当使用new时,函数内的this指向一个新对象并且函数会返回这个对象。看下面的代码:

function Person(name) {
this.name = name;
} var person = new Person("Zakas");
var notAPerson = Person("Zakas"); console.log(person); // [Object object]
console.log(notAPerson); // undefined

一个自然的问题就是:如何判断函数调用时有没有使用new。在ES5中使用instanceof来判断:

function Person(name) {
if (this instanceof Person) {
this.name = name;
} else {
throw new Error("You must use new with Person");
}
} var person = new Person("Zakas");
var notAPerson = Person("Zakas"); // throws an error

上面的代码会判断this是不是Person的实例,如果是那么继续执行,否则抛出错误。这个方法不可靠,因为即使不使用new,this也可以是Person的实例:

function Person(name) {
if (this instanceof Person) {
this.name = name;
} else {
throw new Error("You must use new with Person");
}
} var person = new Person("Zakas");
var notAPerson = Person.call(person, "Zakas");

Person.call的第一个参数是person,它是一个Person实例。所以this也是一个Person实例。也就是说用instanceof没办法判断函数调用时是否使用new。为了解决这个问题,ES6中引入了new.traget:

function Person(name) {
if (typeof new.target !== "undefined") {
this.name = name;
} else {
throw new Error("You must use new with Person");
}
} var person = new Person("Zakas");
var notAPerson = Person("Zakas"); // throws an error

当Person调用时使用new,new.target指向Person,上面的判断语句实际上可以写成new.traget === Person。再看一个例子:

function Person(name) {
if (typeof new.target !== "undefined") {
this.name = name;
} else {
throw new Error("You must use new with Person");
}
} function AnotherPerson(name) {
Person.call(this, name);
} var person = new Person("Zakas");
var notAPerson = new AnotherPerson("Zakas"); // throws an error

上面的代码会报错,因为并没有在调用Person时使用new,new.traget并不指向Person。

注意:new.target只能在函数内部使用,否则会报错的。可以看到,通过使用new.target我们可以判断函数调用时是否使用new。

《理解 ES6》阅读整理:函数(Functions)(六)Purpose of Functions的更多相关文章

  1. 《理解 ES6》阅读整理:函数(Functions)(五)Name Property

    名字属性(The name Property) 在JavaScript中识别函数是有挑战性的,因为你可以使用各种方式来定义一个函数.匿名函数表达式的流行使用导致函数调试困难,在栈信息中难以找出函数名. ...

  2. 《理解 ES6》阅读整理:函数(Functions)(一)Default Parameter Values

    对于任何语言来说,函数都是一个重要的组成部分.在ES6以前,从JavaScript被创建以来,函数一直没有大的改动,留下了一堆的问题和很微妙的行为,导致在JavaScript中使用函数时很容易出现错误 ...

  3. 深入理解ES6箭头函数中的this

    简要介绍:箭头函数中的this,指向与一般function定义的函数不同,比较容易绕晕,箭头函数this的定义:箭头函数中的this是在定义函数的时候绑定,而不是在执行函数的时候绑定. 1.何为定义时 ...

  4. ES6 入门系列 - 函数的扩展

    1函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console.log( ...

  5. 《javascript个人理解,个人整理。》

    万事开头难. 本人做前端工程师,已几年,没有特别大的,已文字方式去做总结. 前段时间,早已经想好,但是迟迟没有去下笔!好在现在陆陆续续的写下去. 我知道这是一个很大的工程,但是我还是想做下去,不为别的 ...

  6. 对word2vec的理解及资料整理

    对word2vec的理解及资料整理 无他,在网上看到好多对word2vec的介绍,当然也有写的比较认真的,但是自己学习过程中还是看了好多才明白,这里按照自己整理梳理一下资料,形成提纲以便学习. 介绍较 ...

  7. es6中的函数

    ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面. function log(x, y = 'World') { console.log(x, y); } log('Hello') // ...

  8. ES6知识整理(4)--数组的扩展

    最近工作比较忙,基本每天都会加班到很晚.处理一些客户端兼容问题以及提升用户体验的优化.也将近一周没更文了,现在继续es6的学习总结. 上篇回顾 ES6知识整理(三)--函数的扩展 扩展运算符 形式是3 ...

  9. 理解 ES6 Generator-next()方法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. PLSQLDeveloper 提示不能初始化?

    原因: oracle数据库是64位的,而 PLSQL Developer 只有32位的! 下载PLSQL_Developer地址: http://pan.baidu.com/share/link?sh ...

  2. asp.net 页面如何将Eval中的时间显示为“yyyy-MM-dd ” 格式

    <table> <tr>    <td style="width:273px;color:#105db5;" valign="top&quo ...

  3. Java(接口与继承)动手动脑

    1>继承条件下的构造方法调用 运行 TestInherits.java 示例,观察输出,注意总结父类与子类之间构造方法的调用关系修改 Parent 构造方法的代码,显式调用 GrandParen ...

  4. sublime插件 cssComb实现css自动排序及格式化

    cssComb是一个实现css代码自动排序,当然顺便也实现了代码的格式化 安装: 首先需要打开sublime搜索安装csscomb插件(前提是已经安装了sublime的package control) ...

  5. 加载音频Audio

    var cameraAudio = new Audio(); cameraAudio.src = 'camera.wav'; // 设置音频对象的属性,预加载视频 var options_audio ...

  6. iOS 8下使用xib/storybord AutoLayout导致的分割线问题

    /*** iOS8 分割线问题 在xib/storyboard下面解决方案 http://qiita.com/yimajo/items/10f16629200f1beb7852 http://www. ...

  7. c#输出、输入

    //输出 Console.WriteLine("这是一行文字");  自动回车的. Console.Write("Hello world");  不带回车的. ...

  8. ue4 plugin的编译加载

    插件Plugin: 本来应该是指一种纯以接口与外界打交道的程序模块,在同一接口背后可以有多种实现,更换实现完全不影响客户端代码(不用重编). 但是在ue4的世界里,插件似乎不是这个意思,仅仅是一种可以 ...

  9. oracle创建用户并导入dmp文件

    SQL命令行执行以下命令:SQL> conn sys/111111 as sysdba; SQL> CREATE USER TEST11 IDENTIFIED BY "11111 ...

  10. EasyUI DataGrid getChecked/getSelections 获取不到数据

    今天使用getChecked获取选择的行,结果总是获取一行数据,于是换用getSelections,结果还是一样,想起之前做的项目,把idField换了下,之后getChecked/getSelect ...