ES6(三) 函数 3

2020-05-09  本文已影响0人  蒋小花_4b6c

1.函数构造器 ( new Function(……) )

2.扩展运算符(…)

3.ES6 的名称属性(函数声明式,匿名函数式,  名称特殊情况)

4.明确函数的双重用途

函数构造器

Function 构造器允许你动态创建一个新函数

Function构造器(JS不常用)与 函数声明形式

普通Function构造器

var add = new Function("first", "second", "return first + second");

console.log(add(1, 1)); // 2

使用默认值的Function构造器

var add = new Function("first", "second = first", "return first + second");

console.log(add(1, 1)); // 2

console.log(add(1)); // 2

使用剩余变量的Function构造器

var pickFirst = new Function("...args", "return args[0]");

console.log(pickFirst(1, 2)); // 1

扩展运算符

与剩余参数关联最密切

剩余参数允许你把多个独立的参数合并到一个数组中(获取传入的实参,放到一个数组中);

扩展运算符则允许将一个数组分割,并将各个项作为分离的参数传给函数。

剩余参数:

function getValue(...value) {

    console.log(value.length);

}

getValue('1', 'w', '3'); // 3

扩展运算符:

let values = [-25, -50, -75, -100]

console.log(Math.max(-60, ...values)); // -25

console.log(Math.max(...values, -60)); // -25

ES6 的名称属性

匿名函数表达式的 流行使得调试有点困难, 所以ES6 给所有函数 添加了name 属性。

function doSomething() {    // 函数声明式

    // ...

}

var doAnotherThing = function() {    // 匿名函数表达式

    // ...

};

console.log(doSomething.name);  // "doSomething"

console.log(doAnotherThing.name); // "doAnotherThing"

function doSomething() {

    console.log('this is doSomething.');

}

doSomething();

var doAnotherThing = function() {

    console.log('this is doAnotherThing.');

};

doAnotherThing();

ES6 名称属性的特殊情况

var doSomething = function() {}

var doAnotherthing = function doAnotherthingElse() {}

var person = {

    get firstName() {

        return 'personName';

    },

    sayName: function() {

        return 'say person name';

    }

}

console.log( doSomething.name ); // doSomething

console.log( doAnotherthing.name ); // doAnotherthingElse

console.log( person.sayName.name ); // sayName

var descriptor = Object.getOwnPropertyDescriptor(person, "firstName");

console.log(descriptor.get.name); // get firstName

person.firstName 实际是个 getter 函数,因此它的名称是"getfirstName"  ,以标明它的特征;

同样, setter 函数也会带有"set" 的前缀

( getter与 setter函数都必须用 Object.getOwnPropertyDescriptor() 来检 索)

函数名称还有另外两个特殊情况:

使用 bind() 创建的函数会在名称属性值之前带有"bound" 前缀;

而使用 Function 构造器创建的函数,其名称属性则会有 "anonymous" 前 缀。

var doSomething = function() {};

console.log(doSomething.bind().name); // bound doSomething

console.log((new Function()).name); // anonymous

明确函数的双重用途

function Person(name) {

    this.name = name;

}

var person = new Person("Nicholas");

var notAPerson = Person("Nicholas");

console.log(person); // [Object object] // Person {name: "Nicholas"}

console.log(notAPerson); // undefined   未使用 new 来调用 Person() 输出了 undefined (并且在非严格模式下给全局对象添加了 name 属性)

console.log(window); // window.name: "Nicholas"

Person 首字母大写是指示其应当使用 new 来 调用的唯一标识,

ES6 中:  JS 提供了两个不同的内部方法: [[Call]] 与 [[Construct]]

未使用 new 进行调用时:  [[call]] 方法会被执行,运行的是代码中显示的函数体。会给全局对象添加属性 ( console.log(window); )

当使用 new 进行调用时:  [[Construct]]  方法则会被执行,负责创建一个被称为新目标的新的对象,使用该新目标作为 this 去执行函数体。被称为构造器。

ES5 中判断函数如何被调用

function Person(name) {

    if (this instanceof Person) {

        this.name = name;   // 使用new

        console.log(this);

    } else {

        throw new Error("You must use new with Person.")

    }

}

var person = new Person("Nicholas"); //[object, object] Person {name: "Nicholas"}

var notAPerson = Person("Nicholas"); // 抛出错误

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 调用区 分开来。

为了解决此问题, ES6 引入了 new.target 元属性

警告:在函数之外使用 new.target 会有语法错误。

上一篇下一篇

猜你喜欢

热点阅读