[ES6]函数

[ES6]函数

  • 常规函数
  • 函数参数的扩展
    • 默认参数
    • 不定参数
  • 箭头函数
    • 箭头函数的优势
  • 箭头函数与常规函数的区别
    • 动态 this
  • 举例说明

常规函数

function test() {
  if (undefined === window.env || null === window.env) {
    window.env = "xxx";
  }
}

函数参数的扩展

默认参数

给参数设置默认值

function fn(name, age = 17) {
  console.log(name + "," + age);
}
fn("Amy", 18); // Amy,18

// 不报错
function fn(name, name) {
  console.log(name);
}
//不报错
function fn(name, name, age) {
  console.log(name);
  console.log(age);
}
// 以下均报错,任何参数设置默认值均报错
//SyntaxError: Duplicate parameter name not allowed in this context
function fn(name, name, age = 17) {
  console.log(name + "," + age);
}
function fn(name = 1, name, age) {
  console.log(name + "," + age);
}
function fn(name, name = 1, age) {
  console.log(name + "," + age);
}

当函数参数列表有同名参数时,只要其中任意参数设置了默认值均会报错

function f(x, y = x) {
  console.log(x, y);
}
f(1); // 1 1,这里的y并不是undefined

function f(x = y) {
  //这里的y也不是作为undefined传递给x
  console.log(x);
}
f(); // ReferenceError: y is not defined

函数参数设置默认值可能导致暂时性死区,在函数参数默认值表达式中,还未初始化赋值的参数值无法作为其他参数的默认值

不定参数

不定参数表示不确定参数的个数,形如,…变量名,由…加上一个具名参数标识符组成。具名参数只能放在参数组的最后,并且有且只有一个不定参数

function f(...values) {
  console.log(values.length);
}
f(1, 2); //2

箭头函数

箭头函数 – =>,箭头函数提供了一种更加简洁的函数书写方式:参数 => 函数体

  • 箭头函数没有参数或者有多个参数,参数位置要用 () 括起来
  • 箭头函数函数体有多行语句,用 {} 包裹起来,表示代码块,当只有一行语句,并且需要返回结果时,可以省略 {} , 结果会自动返回
let test = () => {
  if (undefined === window.env || null === window.env) {
    window.env = "xxx";
  }
};

在函数内容使用 this,常规函数指向 onlineEnv,箭头函数指向 onlineEnv 所在的 scop

// 报错
var f = (id,name) => {id: id, name: name};
f(6,2);  // SyntaxError: Unexpected token :

// 不报错
var f = (id,name) => ({id: id, name: name});
f(6,2);  // {id: 6, name: 2}

箭头函数要返回对象的时候,为了区分于代码块,要用 () 将对象包裹起来

箭头函数的优势

let onlineEnv = (a) => {
  return a * a;
};

返回值只有一行,可以去除{},与 return 关键字

let onlineEnv = (a) => a * a;

如果参数只有一个,可以去除参数的()

let onlineEnv = (a) => a * a;

箭头函数与常规函数的区别

在常规函数中 this 指向的是函数所在对象;

在箭头函数中 this 指向的是外部环境

var func = () => {
  // 箭头函数里面没有 this 对象,
  // 此时的 this 是外层的 this 对象,即 Window
  console.log(this);
};
func(55); // Window

var func = () => {
  console.log(arguments);
};
func(55); // ReferenceError: arguments is not defined

注意:没有 this、super、arguments 和 new.target 绑定

箭头函数体中的 this 对象,是定义函数时的对象,而不是使用函数时的对象

ES6 之前,JavaScript 的 this 对象一直很令人头大,回调函数,经常看到 var self = this 这样的代码,为了将外部 this 传递到回调函数中,那么有了箭头函数,就不需要这样做了,直接使用 this 就行

function fn() {
  setTimeout(() => {
    // 定义时,this 绑定的是 fn 中的 this 对象
    console.log(this.a);
  }, 0);
}
var a = 20;
// fn 的 this 对象为 {a: 18}
fn.call({ a: 18 }); // 18

不可以作为构造函数,也就是不能使用 new 命令,否则会报错

var Person = {
  age: 18,
  sayHello: () => {
    console.log(this.age);
  }
};
var age = 20;
Person.sayHello(); // 20
// 此时 this 指向的是全局对象

var Person1 = {
  age: 18,
  sayHello: function () {
    console.log(this.age);
  }
};
var age = 20;
Person1.sayHello(); // 18
// 此时的 this 指向 Person1 对象

动态 this

var button = document.getElementById("userClick");
button.addEventListener("click", () => {
  this.classList.toggle("on");
});

button 的监听函数是箭头函数,所以监听函数里面的 this 指向的是定义的时候外层的 this 对象,即 Window,导致无法操作到被点击的按钮对象

举例说明

this.id = "console to show this";

const testThis = {
  func1: function () {
    console.log("func1", this);
  },
  func2: () => {
    console.log("func2", this);
  },
  func3: {
    func31: function () {
      console.log("func31", this);
    },
    func32: () => {
      console.log("func32", this);
    }
  }
};
const func4 = function () {
  console.log("func4", this);
};

testThis.func1();
testThis.func2();
testThis.func3.func31();
testThis.func3.func32();

func4();

输出:

func1 {
  func1: [Function: func1],
  func2: [Function: func2],
  func3: { func31: [Function: func31], func32: [Function: func32] }
}
func2 { id: 'console to show this' }
func31 { func31: [Function: func31], func32: [Function: func32] }
func32 { id: 'console to show this' }
func4 <ref *1> Object [global] {
  global: [Circular *1],
  queueMicrotask: [Function: queueMicrotask],
  clearImmediate: [Function: clearImmediate],
  setImmediate: [Function: setImmediate] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  structuredClone: [Function: structuredClone],
  clearInterval: [Function: clearInterval],
  clearTimeout: [Function: clearTimeout],
  setInterval: [Function: setInterval],
  setTimeout: [Function: setTimeout] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  atob: [Function: atob],
  btoa: [Function: btoa],
  performance: Performance {
    nodeTiming: PerformanceNodeTiming {
      name: 'node',
      entryType: 'node',
      startTime: 0,
      duration: 43.73209999501705,
      nodeStart: 2.7523999959230423,
      v8Start: 6.356099992990494,
      bootstrapComplete: 27.509199991822243,
      environment: 14.54169999063015,
      loopStart: -1,
      loopExit: -1,
      idleTime: 0
    },
    timeOrigin: 1680579070496.426
  },
  fetch: [AsyncFunction: fetch]
}

你可能感兴趣的:(JS,javascript,前端,es6)