函数的扩展

1.可以直接为函数的参数指定默认值

function Point(x,y='haha'){}

1.1. 注意

  • 使用参数默认值时,函数不能有同名参数。
  • 参数变量是默认声明的,所以不能用let或const再次声明。
  • 注意一下参数默认值的位置,尽量放在尾部。否则放在前面需要用undefiend(null不行)才能触发默认值。
  • 参数默认值可以和解构赋值默认值结合起来使用
function ha(x,y=1){const x=1;console.log(x)}
const p = new Gha(); // Uncaught SyntaxError: Identifier 'x' has already been declared

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

foo() // undefined 5  

1.2. 函数的length属性

length属性的含义是,该函数预期传入的参数个数。
指定了默认值以后,函数的length属性,将返回指定默认值的参数个数。如果设置了默认值的参数不是尾参数,那么length属性也不再计入后面的参数了。
即length属性会失真。

(function (a = 0, b, c) {}).length // 0
(function (a, b = 1, c) {}).length // 1
(function(...args) {}).length // 0

1.3. 作用域
函数调用时,函数体内部的局部变量x影响不到默认值变量x。

let x = 1;

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

f() // 1
var x = 1;

function foo(x = x) {
  // ...
}

foo() // ReferenceError: x is not defined

请注意下面2个实例

var x = 1;
function foo(x, y = function() { x = 2; }) {
  var x = 3;
  y();
  console.log(x);
}

foo() // 3
x // 1
var x = 1;
function foo(x, y = function() { x = 2; }) {
  x = 3;
  y();
  console.log(x);
}

foo() // 2
x // 1

1.4 应用

- 可以指定参数的默认值;
- 指定参数不得省略(方式1,将默认值设置为抛出错误的函数;方式2 设为undefiend)

2.函数的rest参数(...变量名)

含义:用于获取函数的多余参数.
rest参数(...变量名)搭配的变量是个数组
注意:

  • rest 参数的位置,只能在函数参数的尾端
  • 函数的length属性
  • ...变量名,也叫扩展运算符
  • 应用 数组可直接用在函数参数中
function add(...values) { // 这才是rest参数
  let sum = 0;

  for (var val of values) {
    sum += val;
  }

  return sum;
}

add(2, 5, 3) // 10  非此处是rest参数
add(...[2,5,3]) // 10  数组可直接用在函数参数中

3.严格模式

ES2016 做了一点修改,规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错。
原因:函数的执行顺序:函数参数--》函数体。有时候,参数中使用了非严格模式,参数却能执行,等到函数体才报错,这样不合适,故es6直接禁止掉。

  • 解决方法1: 使用全局的严格模式,非函数的严格模式
  • 解决方法2: 把函数包在一个无参数的立即执行函数里面。
'use strict';

function doSomething(a, b = a) {
  // code
}

const doSomething = (function () {
  'use strict';
  return function(value = 42) {
    return value;
  };
}());

4.name属性--还有函数的name属性;

  • es5 与 es6的区别 对于函数表达式的name属性
  • 构造函数返回的函数实例,name属性值为anonymous
  • bind返回的函数,name属性值前加bound前缀
var f = function () {};

// ES5
f.name // ""

// ES6
f.name // "f"

const bar = function baz() {};

// ES5
bar.name // "baz"

// ES6
bar.name // "baz"

(new Function).name // "anonymous"
function foo() {};
foo.bind({}).name // "bound foo"

(function(){}).bind({}).name // "bound "

5.箭头函数

5.1 写法:(参数)=> XXXX

若XXXX 只有一行, XXX就是返回值
若XXXX 超过一行, xxx就是函数体,返回值需要自己写
注意:当XXXX为{a:1}时,需要用小括号包一下,以免浏览器解析错误

5.2 与rest参数结合
应用1: 将函数参数变为数组

const numbers = (...nums) => nums;

numbers(1, 2, 3, 4, 5)
// [1,2,3,4,5]

const headAndTail = (head, ...tail) => [head, tail];

headAndTail(1, 2, 3, 4, 5)
// [1,[2,3,4,5]]

5.3 注意: 没有自己的this对象。可以绑定this对象
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。即传了啥,就是啥,和函数体无关。

(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

function Timer() {
  this.s1 = 0;
  this.s2 = 0;
  // 箭头函数
  setInterval(() => this.s1++, 1000);
  // 普通函数
  setInterval(function () {
    this.s2++;
  }, 1000);
}

var timer = new Timer();

setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1: 3
// s2: 0

6.总结 es5 es6 函数有哪些属性:

  1. length属性,
  2. name属性

7.双冒号运算符::

es5中有自己的this ,可用call apply bind 进行改变。
es6 中用函数绑定运算符是并排的两个冒号(::),取代call apply bind;
函数绑定运算符是并排的两个冒号(::),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。
obj::function();---obj就是this对象(上下文环境)

8.尾调用优化--未完待续

尾调用的概念:指某个函数的最后一步是调用另一个函数。

类class

类的作用:通过类生成实例对象;优点,比之前的通过构造函数的方式,清晰、形象。更加像面向对象语言。

1.定义类的2种方法:

1.1构造函数的写法

class Haha{
    constructor(){}
    lala(){}
    ...
}
let shili = new Haha();
shili.lala();

1.2 表达式的写法

let Gaga = class me{
constructor(){}
    lala(){return me.name}
    ...
}
let shili = new Gaga();
shili.lala();

2.一些特性,主要是通过类生成实例对象

注意下constructor方法, 这个是类默认的方法,没有定义,也可以调用。

  • 无变量提升

katara1109
468 声望22 粉丝

天助自助者