Python测开28期-偕行-JavaScript函数

1、 函数是什么?

function关键字函数名称和一些语句组成的函数体称{} 之为函数。在 JavaScript中,函数与其他对象一样具有属性和方法,区别是函数可以被调用。如果一个函数中没有使用return语句,则它默认返回 undefined

2、函数定义方式

(1) 函数声明

函数声明是定义一个具有指定参数的函数。

  • 语法:function 函数名([param[, param[, ... param]]]) { statements }

  • 可以在函数声明之前调用函数,不会有语法问题–因为会进行预解析找到函数定义

// 可以在函数声明之前调用函数,不会有语法问题--因为会进行预解析找到函数定义
hoisted(); // "foo"

function hoisted() {
     console.log("foo");
}

(2) 函数表达式

  • 语法:
// 语法
var myFunction = function name([param[, param[, ... param]]]) { statements }

// 匿名写法
var myFunction = function() {
    // statements
}
// 命名写法
var myFunction = function namedFunction(){
    // statements
}
  • 案例:
// 定义一个函数表达式
var foo = function() {}
// 访问foo 变量name属性
foo.name // "foo"

var foo2 = foo
foo2.name // "foo"

var bar = function baz() {}
bar.name // "baz"

console.log(foo === foo2); //true
console.log(typeof baz);// undefined--因为这里是函数表达式,如果把baz函数单独拿出来声明就不是undefined
console.log(bar === baz); // false (errors because baz == undefined)

// 在函数表达式之前调用函数,会有语法错误。
notHoisted(); // TypeError: notHoisted is not a function

var notHoisted = function() {
   console.log("bar");
};

把baz函数单独拿出来声明就不是undefined

// 把baz函数单独拿出来声明就不是undefined
function baz() {}
console.log(typeof baz) // function

(3)动态创建函数

  • 方法一:使用函数表达式创建
var myFunc;
if (num == 0){
  myFunc = function(theObject) {
    theObject.make = "Toyota"
  }
}
  • 方法二:使用 Function 对象创建
var x = 10;
function createFunction1() {
    var x = 20;
    return new Function('return x;'); // 这里的 x 指向最上面全局作用域内的 x
}

(4) 箭头函数 (=>)

A、声明是箭头函数

  • JavaScript 箭头函数大致相当于 python 中的 lambda 函数;
  • 这些是匿名函数,它们有自己的特殊语法,接受一定数量的参数,并在其封闭的作用域的上下文(即定义它们的函数或其他代码)中操作。

B、箭头函数定义

  • 语法一:括号内的是参数列表,后跟“胖箭头”(=>),最后是函数体。
    • 这与传统函数非常相似,我们只是省略 function 关键字并在参数后添加一个胖箭头(=>)。
([param] [, param]) => { statements }
  • 语法二:如果函数体是单个表达式,则可以不使用花括号并将其置于内联中(省略大括号直接将表达式写在一行中)。 表达式的结果将由函数返回。
    • 如果只有一个参数,你甚至可以省略参数的括号。
// 多个参数
const add = (a, b) => a + b;
// 只有一个参数
const getFirst = array => array[0];
  • 语法三:高级语法,如果想要一个对象的单个表达式,请用花括号包裹该对象,返回的就是一个对象;
(name, description) => ({name: name, description: description});

C、箭头函数的特点

(5) 生成器函数

function * 定义一个函数并返回一个 Generator 对象称之为 生成器函数。配合上 yield 关键字可以变成 异步函数。

(6)异步函数 AsyncFunction

可以使用 AsyncFunction 对象,动态创建异步函数。AsyncFunction 并不是一个全局对象,需要通过Object.getPrototypeOf(async function(){}).constructor 来生成。JavaScript 中每个异步函数都是 AsyncFunction 的对象。

// 使用实例
function resolveAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

var AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
var a = new AsyncFunction('a',
                          'b',
                          'return await resolveAfter2Seconds(a) + await resolveAfter2Seconds(b);');
a(10, 20).then(v => {
  console.log(v); // 4 秒后打印 30
});

3、函数参数

(1)默认参数

// 1、参数默认值为 undefined
function multiply(a, b) {
  b = (typeof b !== 'undefined') ?  b : 1;
  return a*b;
}
multiply(5); // 5

// 2、使用默认参数重新上面函数
function multiply(a, b = 1) {
  return a*b;
}
multiply(5); // 5

(2)剩余参数

... 来表示不确定数量的剩余参数,

// 1、语法
function(a, b, ...theArgs) {
  // ...
}

// 2、实例
function multiply(multiplier, ...theArgs) {
  return theArgs.map(x => multiplier * x);
}

var arr = multiply(2, 1, 2, 3);// 把multiplier=2,theArgs=1,2,3传入函数multiply
console.log(arr); // [2, 4, 6]

arguments实参对象

arguments 是一个数组对象,包含函数的实际参数。

function myConcat(separator) {
   var result = ''; 
   var i;

   for (i = 1; i < arguments.length; i++) {
      result += arguments[i] + separator;
   }
   return result;
}

myConcat(", ", "red", "orange", "blue");
// 结果: red, orange, blue,

4、方法

当函数是一个对象的属性时,称之为方法。

(1)方法定义

从ECMAScript 2015开始,采用了更简短的方式来定义方法。

var obj = {
  foo: function() {
    /* code */
  }
};

// 用下面简写的方式代替上面
var obj = {
  foo() {
    /* code */
  }
};

(2) 生成器方法

// 用有属性名的语法定义方法(ES6之前):
var obj2 = {
  g: function*() {
    var index = 0;
    while(true)
      yield index++;
  }
};

// 同一个方法,简写语法:
var obj2 = {
  * g() {
    var index = 0;
    while(true)
      yield index++;
  }
};

var it = obj2.g();
console.log(it.next().value); // 0
console.log(it.next().value); // 1

(3) Async 方法

// 用有属性名的语法定义方法(ES6之前):
var obj3 = {
  f: async function () {
    await some_promise;
  }
};

// 同一个方法,简写语法:
var obj3 = {
  async f() {
    await some_promise;
  }
};

(4) Async 生成器方法

var obj4 = {
  f: async function* () {
    yield 1;
    yield 2;
    yield 3;
  }
};

// 同一个方法,简写语法:
var obj4 = {
  async* f() {
   yield 1;
   yield 2;
   yield 3;
  }
};

(5) get 和 set

使用 get 和 set 关键字将属性与函数关联起来,可以对属性做一些复杂的自定义操作。

5、其他特性

(1) 检测函数是否存在

typeof 操作符可以判断一个函数是否存在。
if ('function' === typeof window.noFunc) {
   // use noFunc()
 } else {
   // do something else
 }

(2) 闭包

闭包(closure)就是通过嵌套函数的方式,缓存嵌套函数及其执行环境,等待下一次调用。当内部函数以某一种方式被任何一个外部函数作用域访问时,一个闭包就产生了。

(3) 预定义函数

JavaScript语言有一些全局函数可用:eval()、isNaN()、parseInt()等。

(4) Function 对象

Function 对象 可以动态创建 函数,实际上每个函数都是一个 Function 对象。