JavaScript学习笔记02
函数
函数的定义与调用
函数定义方式一
function abs(x) { if (x >= 0) { return x; } else { return -x; } }
函数定义方式二:定义匿名函数
var abs = function (x) { if (x >= 0) { return x; } else { return -x; } };
两种方式完全等价,在调用函数时,JavaScript允许传入任意个参数而不影响使用,传入的参数比定义的参数多也没有问题,
关键字 arguments:只在函数内部起作用,指向当前函数的调用者传入的所有参数。最长用于判断传入参数的个数
//关键字 arguements function fun(x) { alert(x);//11 for (var i = 0; i < arguments.length; i++) { var element = arguments[i]; console.log(element);//11,12,13 } } fun(11,12,13);
参数 rest,ES 6 之后引入的参数,用来获取已定义的参数之外的参数值。类似Java中的可变参数的用法
//获取已定义的a,b之外的参数,需要使用arguements关键字 function foo(a,b) { var i,rest=[]; if(arguments.length>2){ for (var i = 2; i < arguments.length; i++) { rest.push(arguments[i]); } } console.log("a = "+a);// 1 console.log("b = "+b);// 2 console.log(rest);// [] } // ES6 之后引入了rest参数,rest参数只能写在后边,前面用...来标识,就不需要再借助arguements 参数, function foo1(a,b,...rest) { console.log("a = "+a);// 3 console.log("b = "+b);// 4 console.log(rest);// [3](5,6,7) } foo1(3,4,5,6,7); // a = 3 // b = 4 // [3](5, 6, 7) foo1(8); // a = 8 // b = undefine // []
注意return语句
JavaScript引擎有一个在末尾自动添加分号的机制
//JS 末尾自动添加分号机制 //这样写没问题 function fun3() { return { name:"sunxin" }; } fun3();//{name:"sunxin"}
function fun3() {
return
{
name:"sunxin"
};
}
fun3();// undefine
函数的变量作用域
使用var声明的变量是有作用域的,如果一个变量在函数内部声明,则该变量的作用域为整个函数体,在函数体外不能引用该变量。
- 不同函数内部的同名变量互相独立互不影响
- JavaScript 函数可以互相嵌套,内部函数可以访问外部函数定义的变量,反之则不行
- 如果内部函数和外部函数的变量重名,则JavaScript在查找变量的时候进行由“内”向“外”查找,如果内部函数定义了与外部函数同名的变量,则内部函数的变量将屏蔽外部函数的变量。
变量提升 :JavaScript 定义函数有个特点,它会先扫描整个函数体的语句,然后把所有生命的变量提升到函数顶部。
全局作用域 :不在人和函数内部定义的变量具有全局作用域,JavaScript有默认有一个全局对象window,全局作用域的变量都会被绑定到window的一个属性。
名字空间 :全局变量都会绑定到window上,不同的JavaScript文件如果如果使用相同的全局变量,或者定义了相同名字的顶层函数,都会造成命名冲突,减少冲突的一个方法就是把自己的所有变量和函数都绑定在一个全局变量中。
局部作用域 : 因为JavaScript的变量作用域实际上是函数内部,我们在for循环中等语句块是无法定义具有局部作用域的变量的。
function foo() {
for (var i=0; i<100; i++) {
//
}
i += 100; // 仍然可以引用变量i
}
为了解决块级作用域,ES6引进了新的关键字let
,用let
替代var
可以申明一个块级作用域的变量
function foo() {
var sum = 0;
for (let i=0; i<100; i++) {
sum += i;
}
i += 1; // SyntaxError
}
常量 : ES6之前是不能声明常量的,ES6之后引入
const
关键字来声明常量,const
和let
都具有块级作用域
方法
在一个对象中绑定函数,称为这个对象的方法
在JavaScript中定义一个people
对象,并绑定一个方法,写法如下
var xiaoming={
name:"xiaoming",
birth:1993,
age: function(){
var y = new Date().getFullYear();
return y - this.birth;
}
};
xiaoming.name;
xiaoming.age();//今年打印出来就是24
绑定在对象上面的方法和普通的函数没有什么区别,但是在它的内部是用了一个特殊变量this
,它始终指向当前变量。
BUT this
变量的用法需要小心,因为它的指向需要根据调用者的情况进行判断。
function getAge() {
var y = new Date().getFullYear();
return y - this.birthday;
}
var people = {
name:"xixi",
birthday:1993,
age:getAge
}
console.log(getAge());//NaN
console.log(people.age());//24
上面的第一个调用返回NaN
,因为直接调用getAge()
方法,this
指向的就是全局对象,即window
。如果在strict
模式下,this指向的是undefine。
apply
可以通过
apply
控制this的指向。在一个独立函数中,根据是否是strict
模式,this
指向undefine
和window
。
function getAge() {
var y = new Date().getFullYear();
return y - this.birthday;
}
var people = {
name:"xixi",
birthday:1993,
age:getAge
}
console.log(people.age()); //24
console.log(getAge.apply(people,[])); //24 指定this指向people。
apply()
方法接收两个参数,第一个参数是需要绑定的this
变量,第二个参数是Array
,表示函数本身的参数。
call
与
apply
十分相似,唯一的区别就是apply是把参数打包成Array再传入,call是直接按参数顺序传入。
装饰器
利用
apply()
,我们还可以动态改变函数的行为。
JavaScript的所有对象都是动态的,即使内置的函数,我们也可以重新指向新的函数。
- 栗子:统计方法被调用了多少次。
1 | var count = 0; |