1.函数定义方式(3种)
//函数声明
function sum(num1,num2){
return num1+num2;
}
//函数表达式
var sum2=function(num1,num2){
return num1+num2;
}
//Function构造函数
var sum3=new Function("nun1","num2","return num1+num2");//不推荐
2."函数是对象,函数名是指针"
function sum4(num1,num2){
return num1+num2;
}
console.log(sum4(10,5));//15
var anotherSum=sum4;//不带圆括号的函数名是访问函数指针,而非调用函数(也不会调用函数)
console.log(anotherSum(20,5));//25
sum4=null;
console.log(anotherSum(30,5));//35
3.函数声明提升:执行代码之前会先读取函数声明,意味着可以把函数声明放在调用它的语句后面。
//先调用
console.log(sum5(10,15));
//再定义(函数定义方式为函数声明)
function sum5(num1,num2){
return num1+num2;
}
//结果:25
//先调用
//console.log(sum6(20,25));
//再定义(函数定义方式为函数表达式)
//var sum6=function(num1,num2){
// return num1+num2;
//}
//报错:Uncaught TypeError: Property 'sum6' of object [object Object] is not a function
另:变量声明提升:变量声明在进入执行上下文就完成了。
if(false){
var a=1;
}
console.log(a);
//a为undefind
//此处a变量声明提升,有声明但未赋值,所以a为undefind,而不是像下面的b(未声明未赋值)一样直接报错
console.log(b);
//报错:Uncaught ReferenceError: b is not defined
再另:变量or函数声明:函数声明会覆盖变量声明,但不会覆盖变量赋值。
var demo;
function demo(){
}
console.log(demo);
//打印结果:function demo(){}
再另的特殊情况:如果在变量声明的同时,对变量进行初始化,情况会有所不同。对同一个变量名,声明变量同时初始化变量优先级高于函数声明。
var demo=1;
function demo(){
}
console.log(demo);
//打印结果:1
4.函数名是变量,可以作为值来使用
function result(someFunction,someArgument){
return someFunction(someArgument);
}
function add(num){
return num+10;
}
console.log(result(add,15));//25
实例:排序
function creatComparisonFunction(proptyName){
return function(object1,object2){
var value1=object1[proptyName];
var value2=object2[proptyName];
if(value1<value2){
return -1;
}else if(value1>value2){
return 1;
}else {
return 0;
}
}
}
var data=[{name:"Annie",age:18},{name:"Bob",age:20},{name:"Cindy",age:15}];
data.sort(creatComparisonFunction("age"));
console.log(data);
5.arguments对象的callee属性,指针指向函数本身
//阶乘实例
function factorial(num){
if(num<=1){
return 1;
}else{
//return num*factorial(num-1);
return num*arguments.callee(num-1);//减少耦合
}
}
console.log(factorial(3));
6.caller属性中保存着调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,它的值为null
function outer(){
inner();
}
function inner(){
//console.log(inner.caller);
console.log(arguments.callee.caller);
}
outer();//function outer(){inner();}
7.ECMAScript中函数是对象,有属性和方法。每个函数都包含两个属性:length(函数期望接收到参数的个数)和prototype每个函数都包含两个非继承而来的方法,apply()和call()
//call()/apply()在特定作用域中调用函数,传递参数
function addSum(num1,num2){
return num1+num2;
}
function callFunction(num1,num2){
//return addSum.apply(this,arguments);//apply(),传入arguments对象
//return addSum.apply(this,[num1,num2]);//apply(),传入数组
return addSum.call(this,num1,num2);//call(),必须把函数的参数逐个列出来
//apply()和call()的区别仅在于接收参数的方式有不同
}
console.log(callFunction(10,5));
//call()/apply()扩充函数赖以生存的作用域
window.color="red";
var my={color:"blue"};
function showColor(){
console.log(this.color);
}
showColor();//red
showColor.call(this);//red
showColor.call(window);//red
showColor.call(my);//blue