ES6 函数的扩展

Posted Mr.隐士

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES6 函数的扩展相关的知识,希望对你有一定的参考价值。

一、 函数 参数默认值

1. 规则

  • (1)ES6 允许为函数的参数设置默认值: 在形参出直接定义即可,不用关键字声明
function ff(x, y = ‘World‘) {
    console.log(x, y);
}

console.log(ff(‘Hello‘)); // Hello World
console.log(ff(‘Hello‘, ‘China‘)); // Hello China
console.log(ff(‘Hello‘, ‘‘)); // Hello
  • (2)函数参数 在形参处默认声明: 规定 函数内不能用 letconst 再次声明,否则会报错
function foo(x = 5) {
    let x = 1; // error
    const x = 2; // error
}
  • (3)函数参数 设置默认值: 不会被记录到 函数.length
    • 函数.length 用于获取形参个数
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
  • (4)函数参数 设置默认值: 参数会在形参处 形成一个单独的作用域(conext)
var x = 1;

function f(x, y = x) {
    console.log(y);
}

f(2) // 2
let x = 1;

function f(y = x) {
    let x = 2;
    console.log(y);
}

f() // 1

2. 函数参数 解构赋值

  • 函数 参数为对象,设置默认值
function foo({
    x = 10,
    y = 5
}) {
    console.log(x, y);
}

foo({})       // 10 5
foo({x: 1})   // 1 5
foo()         // TypeError: Cannot read property ‘x‘ of undefined
function foo({
    x = 10,
    y = 5
} = {}) {
    console.log(x, y);
}

foo({})       // 10 5
foo({x: 1})   // 1 5
foo()         // 1 5
function foo({
    x = 10,
    y
}) {
    console.log(x, y);
}

foo({})       // 10 undefined
foo({x: 1})   // 1 undefined
foo()         // TypeError: Cannot read property ‘x‘ of undefined
  • 重点区分
// 写法一
function m1({x = 0, y = 0} = {}) {
  return [x, y];
}

// 写法二
function m2({x, y} = { x: 0, y: 0 }) {
  return [x, y];
}
// 函数没有参数的情况
m1() // [0, 0]
m2() // [0, 0]

// x 和 y 都有值的情况
m1({x: 3, y: 8}) // [3, 8]
m2({x: 3, y: 8}) // [3, 8]

// x 有值,y 无值的情况
m1({x: 3}) // [3, 0]
m2({x: 3}) // [3, undefined]

// x 和 y 都无值的情况
m1({}) // [0, 0];
m2({}) // [undefined, undefined]

m1({z: 3}) // [0, 0]
m2({z: 3}) // [undefined, undefined]
// 写法三
function m3({x = 1, y = 0} = {}) {
  return [x, y];
}

// 写法四
function m4({x = 1, y} = { x: 0, y: 0 }) {
  return [x, y];
}


m1() // [1, 0]
m2() // [0, 0]

3. 函数参数默认值 的应用

  • 应用一: 指定某一个参数,不能省略
function throwIfMissing() {
  throw new Error(‘Missing parameter‘);
}

function foo(mustBeProvided = throwIfMissing()) {
  return mustBeProvided;
}

foo()
// Error: Missing parameter
  • 应用二: 某一个参数可省略
function foo(optional = undefined) { ··· }

二、 函数 的 rest 参数

  • ES6 定义了 rest 参数,用于获取函数的多余参数(在不确定函数有多少个参数时,最适用)

  • 语法:
    • 函数形参中 (...rest) ,在函数内部 变量 rest 是存储着多余参数的一个真数组

    • rest 只是一个变量,可以为任意值

function add(...values) {
    let sum = 0;
    
    for (var val of values) {
        sum += val;
    }
    
    return sum;
}

add(2, 5, 3) // 10
add(2, 5, 3, 5) // 15
  • rest 参数 约束:

    • ...rest 中包含的参数,不计入 函数.length 中;当然,设置默认值的参数,也不计入 函数.length

    • 函数的 ...rest 参数必须作为函数的最后一个参数,其后 不能再有其他参数(否则 函数初始化时就会报错)

  • 对比 ES5 中的 arguments
    • arguments: 函数内部的一个属性,存储着函数中 所有实参的伪数组arguments 是固定值,函数内部直接访问即可; 箭头函数中不再支持 arguments

    • rest: 函数中的一个参数,存储着多余参数的一个真数组rest 是个变量,声明形参,才能在函数中访问

三、 箭头函数

1. 箭头函数 语法

  • 箭头函数的 主要构成:

    • 箭头函数 参数:不需要参数 或 需要多个参数,就使用 一个圆括号 代表参数部分

    • 箭头函数 函数体:函数体重 多于一条语句,要使用 大括号 将它们括起来

    • 箭头函数 返回值:函数体中 多于一条语句,且有返回值时 return 关键字不能省略

var sum = (num1, num2) => { 
    return num1 + num2; 
}
  • 最简化 的箭头函数 var f = v => v

    • 省略了 参数圆括号代码块中括号return 关键字
var f = v => v;

// 等同于
var f = function(v) {
    return v;
};

2. 箭头函数 this 指向

  • 声明: 箭头函数 内部没有this属性;所以 箭头函数内 this 指向 外层代码块的 this

  • 纠正:
    • ES5 语法中的函数,看this指向时的原则:谁调用了函数 this就指向谁

    • ES6 语法中的函数,分析this指向,只要找到箭头函数外层this指向即可(而不是看谁调用的函数)

<script>
    const fn1 = {
        name: function() {
            console.log(this);  // fn1
        }
    }

    fn1.name();

    const fn2 = {
        name: () => {
            console.log(this);  // window
        }
    }

    fn2.name();
</script>
<script>
    let box1 = document.getElementById(‘box1‘);
    box1.name = ‘wang‘
    this.name = ‘zhang‘;
    
    box1.addEventListener(‘click‘, function() {
        console.log(this.name);     // ‘wang‘ 因为是dom对象,调用了回调函数
    });
    
    
    let box2 = document.getElementById(‘box2‘);
    box2.name = ‘wang‘
    this.name = ‘zhang‘;
        
    box2.addEventListener(‘click‘, () => {
        console.log(this.name);     // ‘zhang‘ this.指向外层的this
    });
</script>
  • 借用方法 callapplybind ,不能改变 this指向
var a = 2;
var obj = {
    a: 100
};

var fn1 = (a) => {
    console.log(this.a);
};

var fn2 = function(a) {
    console.log(this.a);
};
   
    
fn1.call(obj);    // 2
fn2.call(obj);    // 100

3. 箭头函数 的约束

  • 箭头函数 不能当作 构造函数(因为 自身没有 this 机制)

  • 箭头函数内 不能使用arguments对象, 用 rest 参数代替

  • 箭头函数 中没有 argumentssupernew.target 这是三个变量, 均指向外层函数 的变量

四、 函数的 name 属性 被写入标准

  • 函数的 name 属性, 早就被浏览器广泛支持,但是直到 ES6,才将其写入了标准

  • 对比:
    • 写入标准之前:将 匿名函数 赋值给一个变量;访问 函数.name 返回空字符串

    • 写入标准之后:将 匿名函数 赋值给一个变量;访问 函数.name 返回 变量名


const test = function baz() {};

console.log(test.name); // ES5输出:""
console.log(test.name); // ES6输出:"baz"

五、 函数内 关于 严格模式的约束

  • ES2016 规定: 函数参数 如果使用了默认值、解构赋值、扩展运算符,函数内部就不能显式设定为严格模式(否则会报错)

  • 原因猜想: (待证实)可理解为函数式一个整体,函数 执行的时候:先执行函数参数,然后再执行函数体;函数执行到中间 发现语法 要遵循 严格模式,就会报错

  • 解决方案:

// 方案一:
‘use strict‘;

function doSomething(a, b = a) {
  // code
}
// 方案二:
const doSomething = (function () {
    ‘use strict‘;
    return function(value = 42) {
        return value;
    };
}());

以上是关于ES6 函数的扩展的主要内容,如果未能解决你的问题,请参考以下文章

ES6函数的扩展

ES6扩展——函数扩展之剩余函数

ES6---函数的扩展之函数的默认值

ES6 入门系列 - 函数的扩展

ES6 入门系列 - 函数的扩展

函数的扩展--ES6