xfshen

导航

《理解 ES6》阅读整理:函数(Functions)(六)Purpose of Functions

明确函数的双重作用(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。

posted on 2016-10-24 20:01  xfshen  阅读(385)  评论(0编辑  收藏  举报