在 ES5 中判断函数如何被调用

在 ES5 中判断函数是不是使用了 new 来调用(即作为构造器),最流行的方式是使用 instanceof ,

例如:

    function Person(name) {
            if (this instanceof Person) {
                this.name = name; // 使用 new
            } else {
                throw new Error("You must use new with Person.")
            }
        }
        var person = new Person("Nicholas");
        var notAPerson = Person("Nicholas"); // 抛出错误

此处对 this 值进行了检查,来判断其是否为构造器的一个实例:若是,正常继续执行;否 则抛出错误。这能奏效是因为 [[Construct]] 方法创建了 Person 的一个新实例并将其赋值 给 this 。可惜的是,该方法并不绝对可靠,因为在不使用 new 的情况下 this 仍然可能 是 Person 的实例,正如下例:

       function Person(name) {
            if (this instanceof Person) {
                this.name = name; // 使用 new 
            } else {
                throw new Error("You must use new with Person.")
            }
        }
        var person = new Person("Nicholas");
        var notAPerson = Person.call(person, "Michael"); // 奏效了!

调用 Person.call() 并将 person 变量作为第一个参数传入,这意味着将 Person 内部的 this 设置为了 person 。对于该函数来说,没有任何方法能将这种方式与使用 new 调用区 分开来。

new.target 元属性

为了解决这个问题, ES6 引入了 new.target 元属性。元属性指的是“非对象”(例如 new ) 上的一个属性,并提供关联到它的目标的附加信息。当函数的 [[Construct]] 方法被调用 时, new.target 会被填入 new 运算符的作用目标,该目标通常是新创建的对象实例的构造 器,并且会成为函数体内部的 this 值。而若 [[Call]] 被执行, new.target 的值则会是 undefined 。

通过检查 new.target 是否被定义,这个新的元属性就让你能安全地判断函数是否被使用 new 进行了调用。

	function Person(name) {
         if (typeof new.target !== "undefined") {
            this.name = name; // 使用 new 
         } else { throw new Error("You must use new with Person.") }
    } 
    var person = new Person("Nicholas");
   	var notAPerson = Person.call(person, "Michael"); // 出错! 

使用 new.target 而非 this instanceof Person , Person 构造器会在未使用 new 调用时 正确地抛出错误。 也可以检查 new.target 是否被使用特定构造器进行了调用,例如以下代码:

        function Person(name) {
            if (new.target === Person) {
                this.name = name; // 使用 new 
            } else { throw new Error("You must use new with Person.") }
        }
        function AnotherPerson(name) { 
        	Person.call(this, name); 
        }
        var person = new Person("Nicholas");
        var anotherPerson = new AnotherPerson("Nicholas"); // 出错!

在此代码中,为了正确工作, new.target 必须是 Person 。当调用 new AnotherPerson(“Nicholas”) 时, Person.call(this, name) 也随之被调用,从而抛出了错误, 因为此时在 Person 构造器内部的 new.target 值为 undefined ( Person 并未使用 new 调用)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值