5、函数

定义函数

function sayHello(){
    return 'Hello';
}
var sayHello = function(){
    return 'Hello';
};

函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。

如果没有return语句,函数执行完毕后也会返回结果,只是结果为undefined

两种定义方式的区别:

函数的传参

function sayHello(name){
    console.log('Hello ' + name);
}
//正常传参
sayHello('lucy');
//多传参数,不影响,函数只会用第一个
sayHello('tom','james');
//少传参数,函数会使用undefined
sayHello();

// Hello lucy
// Hello tom
// Hello undefined

arguments

JavaScript还有一个免费赠送的关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array

function sayHello(name){
    for(let i = 0;i < arguments.length;i++){
        console.log(arguments[i])
    }
}

sayHello('lucy','tom')

// lucy
// tom

rest

由于JavaScript函数允许接收任意个参数,于是我们就不得不用arguments来获取所有参数

为了获取除了已定义参数ab之外的参数,我们不得不用arguments,并且循环要从索引2开始以便排除前两个参数,这种写法很别扭,只是为了获得额外的rest参数,有没有更好的方法?ES6标准引入了rest参数

function test(a,b,...rest){
    console.log(rest);
}

test(1,2,3,4,5,6)

// [ 3, 4, 5, 6 ]

名字空间

全局变量会绑定到window,nodejs中是global上,不同的JavaScript文件如果使用了相同的全局变量,或者定义了相同名字的顶层函数,都会造成命名冲突,并且很难被发现。

减少冲突的一个方法是把自己的所有变量和函数全部绑定到一个全局变量中

许多著名的JavaScript库都是这么干的:jQuery,YUI,underscore等等

var $ = {}

msg = 'Hello'

function say(){
    console.log('Hello')
}

$.msg = msg
$.say = say

解构赋值

从ES6开始,JavaScript引入了解构赋值,可以同时对一组变量进行赋值,就是把一个数组的元素分别赋值给几个变量

var [a,b,c] = [10,20,30]

console.log(a)
console.log(b)
console.log(c)

// 10
// 20
// 30

对象方法

在一个对象中绑定函数,称为这个对象的方法

var lucy = {
    name:'lucy',
    sayHello: function(){
        console.log('Hello,I\'m ' + this.name)
    }
}

lucy.sayHello()

// Hello,I'm lucy

在一个方法内部,this是一个特殊变量,它始终指向当前对象

但是如果在方法外调用,this的指向就不确定了,在web中this指向window,在nodejs中this指向global

apply

我们可以使用apply来指定函数中this的指向

var lucy = {
    name:'lucy',
}

function sayHello(){
    console.log('Hello,I\'m ' + this.name)
}

sayHello()

//使用apply
sayHello.apply(lucy,[])

// Hello,I'm undefined
// Hello,I'm lucy

call

call和apply的功能一样,只不过在传参的方式不一样,apply是把参数装在数组里面,call是直接传

var lucy = {
    name:'lucy',
}

function sayHello(a,b){
    console.log('Hello,I\'m ' + this.name)
}

sayHello(1,2)

//使用apply
sayHello.call(lucy,1,2)

// Hello,I'm undefined
// Hello,I'm lucy

闭包

函数可以作为返回值进行返回,而返回的这个函数可以在后续执行,这种行为成为闭包,和python中的闭包类似

注意:闭包的函数里面不要引入任何后续可能发生变化的值,例如循环的值

function func1(){
    return function func2(){
        return '你好'
    }
}

f = func1()

console.log(f())

箭头函数

x => x * x
//相当于
function(x){
    return x * x;
}
//如果参数不是一个就需要使用括号把参数括住,如果函数体不是一行,就需要使用大括号
(x,y) => {
    x += 1;
    y += 1;
    return 
}