JavaScript函数、闭包

函数

函数实际上就是对象,因此 Function 有自己的属性和方法。函数名是指向函数对象的指针。

函数定义方式有:函数声明、函数表达式、箭头函数、构造函数。

函数声明

函数声明后不会立即执行,会在我们需要的时候调用。

function functionName(a,b){
	return a + b;
}

函数声明的语法中不含分号,因分号是用来分隔可执行 JavaScript 语句,而函数声明不是一个可执行语句,所以不以分号结束。

函数表达式(匿名函数)

通过一个表达式定义,即创建一个函数再把它赋值给一个值,这样创建的函数叫做匿名函数(函数没有名称)。

var x = function(a,b){
	return a + b;
};

函数表达式没有函数提升。

箭头函数

ES6 新增了箭头函数,使得表达式更简洁。

箭头函数不带大括号会隐式的返回这行代码的值。

//多个参数或者没有参数需要带圆括号
(多个参数或者没有参数) => {函数声明};

//只有一个参数时,圆括号是可选的
单一参数 => {函数声明};

箭头函数简介的语法非常适合嵌入函数的场景:

son.addEventListener('click', function () {
    alert('son');
}, true);
//箭头函数的简介语法
son.addEventListener('click', () => {
	alert('son');
}, true);

构造函数(不推荐)

最后一种定义函数的方式是使用 Function()构造函数。这个构造函数接收任意多个字符串参数,最后一个参数始终会被当成函数体,而之前的函数都是新函数的参数。

var function = new Funciton("a","b","return a + b");
虽然我们不推荐使用这种定义函数的方式,
但把函数想象为对象,把函数名想象为指针是很重要的。

函数提升

JavaScript 引擎在任何代码执行之前,会先读取函数声明,并在执行上下文中生成函数定义,这个过程称为函数提升。

//没问题
console.log(sum(a,b));
function sum(a,b){
	return a * b;
}

//会出错
console.log(sum(a,b));
const sum = function(a,b){
	return a * b;
};

函数参数

ECMAScript 函数既不关心传入参数的个数,也不关心传入参数的数据类型。

之所以会这样,主要是因为 ECMAScript 函数的参数在内部表现为一个数组。函数被调用时总会接收一个数组,但函数并不关心这个数组中包含什么。

默认参数

ES5及以前,实现默认参数的一种常用方式是检测某个参数是否等于 undefined ,如果是则意味着没有传这个参数,那就给它赋一个值:

function myFunction(x,y){
	if(y === undifined){
		y = 0;
	}
}

但在 ES6 后就不用这么麻烦,因为它支持显示定义默认参数了。

function myFunction(x,y = 0){
	//代码块
}

函数内部

在 ES5 中,函数内部存在两个特殊的对象:arguments 和 this。在 ES6 中,又新增了 new.target 属性。

arguments 对象

JavaScript 函数有个内置的对象 arguments 对象。

arguments 对象包含了函数调用的参数数组。

通过 arguments 对象可以很方便的找到函数参数。

	x = sumAll(1, 123, 500, 115, 44, 88);
	
	function sumAll() {
	    var i, sum = 0;
	    for (i = 0; i < arguments.length; i++) {
	        sum += arguments[i];
	    }
	    return sum;
	}

this 对象

this 对象用来引用把函数当作方法调用的上下文对象。this 到底引用哪个对象必须到函数被调用时才能确定。

	function myFunction() {
	    return this;
	}
	myFunction();                // 返回 window 对象

new.target 对象

函数既可以作为构造函数来实例化一个对象,也可以作为方法被调用。ES6新增了用来检测函数的用途的属性 new.target 。

当函数用来实例化一个对象时,new.target 将引用被调用的构造函数;如果用来作为方法被调用,则 new.target 的值是 undefined 。

函数的属性

前面提到函数是对象,因此有属性和方法。

每个函数都有两个属性:length 和 prototype。

  • length:保存函数定义的命名参数的个数。
	function sum(num1,num2){
		return num1 + num2;
	}
	console.log(sum.length);//2
  • prototype:保存公共方法,如toString ( )、valueOf ( )等方法,进而可以被所有实例共享。

函数的方法

函数有两个预定义的方法:call ( ) 和 apply ( )。

这两个方法都用来调用函数。且第一个参数必须是 this 或调用函数的对象本身。

区别在于传参的方式不同。call( )传参必须一个一个列出来。

function myFunction(a, b) {
    return a * b;
}
myObject = myFunction.call(myObject, 10, 2);     // 返回 20
function myFunction(a, b) {
    return a * b;
}
myArray = [10, 2];
myObject = myFunction.apply(myObject, myArray);  // 返回 20

闭包

闭包实际上是一种利用作用域链的机制来保护私有变量的机制。在函数调用期间形成一个不销毁的栈环境。通常体现为嵌套函数里面的匿名函数。

	var add = (function () {
	    var counter = 0;
	    return function () {
	    return counter += 1;
	    }
	})();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值