call与apply
call与apply是为了改变某函数运行时的上下文(this的指向)而存在的。
func1.call(this, arg1, arg2); //在参数个数确定时使用
//或者
func1.apply(this, [arg1, arg2]); //在参数个数不确定时使用。
call和apply是为了动态改变this而出现的,当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作。
var domNodes = Array.prototype.slice.call(document.getElementsByTagName('* '));
这样domNodes就可以应用Array下的所有方法。
函数声明
函数声明是做了完全提升的,这使你在函数声明前就可以进行函数调用。变量声明是部分提升,只有声明会被提升,赋值(包括函数表达式)操作不会被提升,因此变量声明提前,但是赋值不会被覆盖。
function fn(flag) {
if (flag) {
var getValue = function () { return 'a'; }
} else {
var getValue = function () { return 'b'; }
}
return getValue();
}
//等价于
function fn (flag) {
var getValue;
getValue = function() { return 'a';}
getValue = function() {return 'b';}
if(flag) {
}
else {
}
}
因此无论flag为何值,返回的方法始终为重写后的方法。
不能在条件语句中声明函数
不得在非函数的代码块中声明函数,最常见的情况就是if和try语句。
在大多数情况下,都不会报错,但不建议这样使用。
if (true) {
var f = function () {};
}
f() // undefined
if (true) {
function f1() {}
}
f1() // 不报错
如果true
改回false
,在Chrome53
版本中,会报错。
函数本身的作用域
var a = 1;
var x = function () {
console.log(a);
};
function f() {
var a = 2;
x();//x在函数体外声明,绑定外层作用域。
}
f() // 1
函数执行时所在的作用域,是定义时的作用域,而不是调用时所在的作用域。
函数参数传递方式
函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递(passes by value)。这意味着,在函数体内修改参数值,不会影响到函数外部。
var p = 2;
function f(p) {
p = 3;
}
f(p);
p // 2
如果写成全局对象,就成了传址传递。
如果函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递(pass by reference)。也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。
var obj = {p: 1};
function f(o) {
o.p = 2;
}
f(obj);
obj.p // 2
如何是对象整体赋值,不会影响原来的实际参数。
高阶函数
一个函数接收另一个函数作为参数,这种函数就称之为高阶函数。
闭包
function lazy_sum(arr) {
var sum = function () {
return arr.reduce(function (x, y) {
return x + y;
});
}
return sum;
}
函数lazy_sum
中又定义了函数sum
,并且,内部函数sum
可以引用外部函数lazy_sum
的参数和局部变量,当lazy_sum
返回函数sum
时,相关参数和变量都保存在返回的函数中,这种称为闭包(Closure)
。
'use strict';
function create_counter(initial) {
var x = initial || 0;
return {
inc: function () {
x += 1;
return x;
}
}
}
var c1 = create_counter();
c1.inc(); // 1
c1.inc(); // 2
c1.inc(); // 3
在返回的对象中,实现了一个闭包,该闭包携带了局部变量x
,并且,从外部代码根本无法访问到变量x。换句话说,闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来。
返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
箭头函数
x => x * x
//上面的箭头函数相当于:
function (x) {
return x * x;
}
箭头函数完全修复了this的指向,this总是指向词法作用域,也就是外层调用者obj:
var obj = {
birth: 1990,
getAge: function () {
var b = this.birth; // 1990
var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象
return fn();
}
};
obj.getAge(); // 25
Link