Web笔记(五)——JavaScript之变量,函数与方法

变量

    在JavaScript中,用var声明的变量实际上是有作用域的。如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量。如果两个不同的函数各自申明了同一个变量,那么该变量只在各自的函数体内起作用。换句话说,不同函数内部的同名变量各自独立,互不影响:

'use strict';

function foo() {
    var x = 1;
    x = x + 1;
}

function bar() {
    var x = 'A';
    x = x + 'B';
}

由于JavaScript的函数可以嵌套,此时,内部函数可以访问外部函数定义的变量,反过来则不行:

'use strict';

function foo() {
    var x = 1;
    function bar() {
        var y = x + 1; // bar可以访问foo的变量x!
    }
    var z = y + 1; // ReferenceError! foo不可以访问bar的变量y!
}

    不在任何函数内定义的变量就具有全局作用域,实际上,JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性上。
    由于JavaScript的变量作用域实际上是函数内部,我们在for循环等语句块中是无法定义具有局部作用域的变量的:

'use strict';

function foo() {
    for (var i=0; i<100; i++) {
        //
    }
    i += 100; // 仍然可以引用变量i
}

    ES6引入了新的关键字let,用它来代替var可以申明一个块级作用域变量:

'use strict';

function foo() {
    var sum = 0;
    for (let i=0; i<100; i++) {
        sum += i;
    }
    // SyntaxError:
    i += 1;
}

函数

(1) 函数的定义:JavaScript的函数是Function类的一个实例。函数名为引用类型变量,指向该函数对象。它有三种定义的方法:
方法1:定义全局变量

function sum(num1,num2){
    return num1+num2;
}

方法2:字面量定义

var sum = function(num1,num2){
    return num1+num2;
}

方法3:Function实例

var sayHi = new Function("sName","sMessage",//这两个是变量名
                         "alert('hello,'+sName+sMessage);");//这是函数体
sayHi("Zhang","come here!");

注:第一种方法定义了window对象的一个方法,也是一个变量。第二种和第三种方法直接把函数定义为一个变量
    需要注意的是,函数体内部语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。如果没有return语句,函数执行完毕后,也会返回结果,只是结果为undefined
    因为JavaScript允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没有问题,虽然函数内部并不需要这些参数,如此下面的例子:

function abs(x){
    if(x >= 0){
        return x;
    }else{
        return -x;
    }
}
abs(10);//返回10
abs(-9);//返回9
abs();//返回NaN
abs(10,'jhjhdhd');//返回10

(2)arguments
    JavaScript还有一个关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。它类似于Array,但它不是一个Array。利用arguments,我们可以获得调用者传入的所有参数。也就是说,即使函数不定义任何参数,还是可以拿到参数的值。如下面例子:

function abs(){
    if(arguments.length == 0){
        return 0;
    }
    var x = arguments[0];//获得传入的参数里的第一个元素
    return x >=0 ? x:-x;
} 

实际上,arguments最常用于判断传入参数的个数,如下面的例子:

// foo(a[, b], c)
// 接收2~3个参数,b是可选参数,如果只传2个参数,b默认为null:
function foo(a,b,c){
    if(arguments.length == 2){
        // 实际拿到的参数是a和b,c为undefined
        c = b; // 把b赋给c
        b = null; // b变为默认值
     }
}
要把中间的参数b变为“可选”参数,就只能通过arguments判断,然后重新调整参数并赋值。

(3)rest参数
下面给出一个例子:

function foo(a,b,...rest){
    console.log('a=' + a);
    console.log('b=' + b);
    console.log(rest);
}
foo(1,2,3,4,5);
//结果:a = 1; b = 2; Array[3,4,5];
foo(1)
//结果:a = 1;b = undefined; Array[]

    rest参数只能写在最后,前面使用“…”标识,从运行结果来看,传入的参数先绑定a、b,多余的参数以数组形式交给变量rest,如果传入的参数连正常定义的参数都没填满,那么rest参数会接收一个空数组。
    下面是一个函数,它可以接收任意个参数并返回它们的和。

function sum(...rest) {
   var sum = 0;
   for(i = 0;ireturn sum;
}

方法

定义:在一个对象中绑定函数,称为这个对象的方法。如下面的一个例子:

var xiaoming{
    name: 'David',
    birth: 1990,
    age: function(){
        var y = new Date().getFullYear();
        return y-this.birth;
    }
};
xiaoming.age; // function xiaoming.age()
xiaoming.age(); // 今年调用是25,明年调用就变成26了

    上面的例子中,使用了this关键字,在一个方法内部,this是一个特殊变量,它始终指向当前对象,也就是xiaoming这个变量。所以,this.birth可以得到xiaoming的birth属性。如果JavaScript的函数内部调用了this,那么这个this到底指向谁,是视情况而定的。如下面的例子:

function getAge(){
    var y = net Date().getFullYear();
    return y-this.birth;
}
var xiaoming = {
    birth: 1990,
    age: getAge
};
//调用
xiaoming.age();//25 正常结果,这里的this指向小明
getAge();//NaN,这里的this指向window

    虽然在一个独立的函数调用中,根据是否是strict模式,this指向undefined或window,不过,我们可以使用apply和call来控制this指向。
(1)apply
要指定函数的this指向哪个对象,可以用函数本身的apply方法,它接收两个参数,第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数。比如下面的例子:

function getAge(){
    var y = new Date().getFUllYear();
    return y-this.birth;
}
var xiaoming = {
    birth:1990,
    age:getAge
};
xiaoming.age();//25
getAge.apply(xiaoming,[]);//25,this指向xiaoming,getAge的参数为空,所以这里传的Array也为空。

(2)call
call()方法与apply()方法相似,唯一的区别是:apply()把参数打包成Array再传入,而call()是把参数按顺序传入。比如调用Math.max(3,4,5),分别用apply()和call()实现如下:

Math.max.apply(null,[3,4,5]);//5
Math.max.apply(null,3,4,5);//5

对于普通函数调用,我们通常把this绑定为null。

你可能感兴趣的:(前端学习笔记)