JS函数的深入理解

一、JS函数的本质

JS函数本质就是一种对象!!!
编写者完全可以用操作对象的方式去操作函数

var obj = {

};

function fn() {

}

/**
 * 分别向对象和函数添加属性值,以验证函数其实就是一类对象
 */
obj.info = "对象";
fn.info = "函数";

console.log("obj是" + obj.info); // 正常打印"obj是对象"
console.log("fn是" + fn.info); // 正常打印"fn是函数"

JS函数名与变量有着相似的特性,函数名用于找到函数(对象)在内存中的位置
当仅输出函数名(变量名)时,将打印函数体(对象)的有关信息;
当输出函数名+参数列表时,将打印函数执行后返回的结果。

/**
 * 直接声明一个函数名为fn1的函数(对象)
 */
function fn1() {
	return "我是命名函数";
}

/**
 * 将一个匿名函数(对象)赋值给变量fn1
 */
var fn1 = function() {
	return "我是匿名函数";
};

/**
 * 用构造法实例一个函数对象,将其赋值给变量fn3
 */
var fn3 = new Function("return '我是new出来的函数'");

console.log(fn1); // 输出函数fn1的信息
console.log(fn1()); // 输出函数fn1执行后返回的结果——"我是命名函数"
console.log(fn2); // 输出变量fn2所指向的匿名函数的信息
console.log(fn2()); // 输出fn2执行后返回的结果——"我是匿名函数"
console.log(fn3); // 输出变量fn3所指向的匿名函数的信息
console.log(fn3()); // 输出fn3执行后返回的结果——'我是new出来的函数'

由于JS弱类型的检测机制,编写者将其它类型的值赋给函数变量时也不会出现问题,它同普通的变量赋值一样。

function fn1() {
	return "我是命名函数";
}

var fn1 = function() {
	return "我是匿名函数";
};

var fn3 = new Function("return '我是new出来的函数'");

/**
 * 将任意的整型数值赋值给fn1、fn2和fn3
 */
fn1 = 99;
fn2 = 100;
fn3 = 101;

console.log(fn1); // 正常打印99
console.log(fn2); // 正常打印100
console.log(fn3); // 正常打印101

值得注意的是,以var方式引导函数的变量在预解析时同样会被初始化为undefined,如果在声明语句前调用该函数将无效,这一点与以function命名形式声明的函数不同。

consolo.log(fn); // 显示undefined
console.log(fn()); // 报错,提示fn不是一个函数

var fn = function() {
	return "我是匿名函数";
}

二、函数调用的特殊情况

1.匿名函数的直接调用

当function作为关键字出现在句首时,会被JS视为命名函数进行解析,所以匿名函数的直接调用需要添加合法的字符以进行区分

/**
 * 通过添加运算符进行匿名函数的调用
 */
!function(){

}();

/**
 * 通过添加括号进行匿名函数的调用
 */
(function(){

 })();
2.方法的调用

对象方法的调用一般使用:对象名.方法名(参数列表)
也可以使用:对象名[“方法名”] (参数列表)(可以传字符串变量)
当遇到特殊字符开头的方法名时,通常会使用到后者。

var obj = {
	info1: function(){
		return "我是info1方法";
	},
	'info2': function(){
		return "我是info2方法";
	}
};

var name = "info2";

console.log(obj.info1());
console.log(obj.info2());
console.log(obj['info2']());
console.log(obj[name]());
3.函数的间接调用

每个函数对象都有call()apply()两个方法,这两个方法可以改变函数this的指向,间接传参并调用函数。

var num = 1;

var obj = {
	num: 2,
	add: function(num) {
		console.log(this.num + num);
	}
};

var array = [3];

obj.add(3); // 将输出2 + 3 == 5
obj.add.call(window, 3); // 将输出1 + 3 == 4
obj.add.apply(window, array); // 将输出1 + 3 == 4 

三、可变参数列表

当函数参数的数量不确定的时候,可以用arguments对象进行可变参数操作。
arguments是一个形态类似数组的对象,每个函数都包含这个对象,arguments按顺序存储了所有的参数,对应的属性名从0开始递增。

function fn(a, b, c) {
	console.log(arguments);
}

fn(10, 20, 30);

打印结果:
Arguments {
        0: 10
        1: 20
        2: 30
}


arguments.callee()方法即指代函数本身,可以直接通过其调用函数

function fn() {
	return arguments.callee;
}

console.log(fn()); // 将打印出函数fn的信息

可以使用arguments.length属性对传参操作进行检查

function fn(a, b) {
	// 若函数接收到的参数个数与函数定义的形参个数不相等,则抛出异常
	if (arguments.length != fn.length) {
		throw new Error("The number of parameters is illegal!");
	}
	
	return a + b;
}

console.log(fn(1, 5)); // 正常计算出6
console.log(fn(1)); // 抛出Error
console.log(fn(1, 5, 8)); // 抛出Error
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值