01 函数的声明方式
- 函数的声明语句
function 函数名(函数形参){
函数内容
}
- 函数表达式:将一个匿名函数赋值给一个变量
var halo = function (){}
PS:有这样一种写法
var halo = function abc(){}
如果此时直接console.log(abc);会直接报错
在函数表达式中halo为变量名称,相当于函数的实参可以在函数内调用也可在函数外调用。abc是函数名称,相当于函数的形参,只能在函数内调用
- Function构造函数
new Function();
var fn = new Function( 'x' , 'y' , 'return x+y;' ); 等同于 Function fn(x, y){ return x+y; };
02 函数的返回值
- 如果函数没有返回值 打印函数显示为undefined
- 函数内return后的语句有可能执行
例如 try{return 0};catch(e){return 1};finally{return 2} 不论执行try还是catch语句finally都会执行 - 如果函数调用时在前面加上new前缀,且返回值不是一个对象,或者没有返回值,则返回该函数对象(this)
function fn(){
return 1;
}
var test = new fn();
console.log(test);//返回的是整个fn函数
如果返回值是一个对象 则返回该对象
03 函数的调用
- 函数调用模式
function add(x,y){
return x + y;
}
var sum =add(3,4);
- 方法调用模式
var obj = {
//fn为obj对象的方法
fn:function(){
console.log('函数内容');
}
}
obj.fn();
- 构造函数调用模式
function fn() {
return 1;
}
var test = new fn();
console.log(test);
- 间接调用模式 call({},1,2) apply({},[1,2])
var obj = {
a: 10
}
function sum(x, y) {
console.log(this);
return x + y + this.a;
}
console.log(sum());
//如果没有下两行代码,sum函数里指向的是window
console.log(sum.call(obj, 1, 2));
//这一行可以让sum函数里的this指向obj对象
console.log(sum.apply(obj, [1, 2]));
//功能几乎与call一样 只是后面的实参要以数组形式写出
04 函数的参数
- 函数传递进来的参数没有限制 可以不传参数 可以穿任意数据类型的参数 可以传多个参数(函数的形参只有一个)
- 同名形参 在非严格模式下
function fn(x,x,x){
return x;
}
console.log(fn(1,2,3));
//此时打印出来的是3 严格模式下报错
- 参数个数
//实参比形参数量少
function fn(x,y,z){
console.log(x,y,z);//打印出来的值为1,2,undefined
}
fn(1,2);
//实参比形参数量多,考虑arguments
function fn(){
//arguments不是真正数组 是类数组 可以通过[]调用
console.log(arguments[0],arguments[1],arguments[2]);
}
fn(1,2,3);
05 函数重载
//函数不存在重载现象第二个add函数会覆盖第一个add
function add(a){
return a + 1;
}
function add(a,b){
return a +b +1;
}
alert(add(1));//打印出来的是NaN 因为会执行第二个add b没定义
06 函数属性
- length属性 形参的个数
- arguments属性 实参的个数
function add(x,y){
console.log(argunments.length);//4
console.log(add.length);//2
}
add(1,2,3,4);
- name属性 当前函数的名字
var fn = function(){};
console.log(fn.name);//fn
var fn2 = function aaa(){};
console.log(fn2.name);//aaa
- prototype属性 (后面有讲解)
function fn(){}
console.log(fn.prototype);//打印一个对象 该对象为fn的原型(父级)对象
07 函数call()、apply()方法使用
- 找出数组最大元素
var arr = [4, 8, 23 ,1 ,66 ,2];
var max = Math.max.apply(null, arr);//null在非严格模式下指向window
console.log(max);//66
- 将类数组(argument)转化成数组
function add(){
var arr = Array.prototype.slice.apply(arguments);
///Array.prototype为add的原型对象 slice方法为截取数组值的方式
//将arguments类数组转化为数组的原因是类数组有许多数组的方法不能调用
}
add(1,2,3);
- 数组追加
var arr = [];
Array.prototype.push.apply(arr,[1,2,3,4]);//arr=[1,2,3,4]
- 利用call和apply做继承
function Animal(name, age) {
this.name = name;
this.age = age;
// console.log(age);
this.sayage = function () {
console.log(this.age);
}
}
function Cat(name, age) {
Animal.call(this, name, age);//继承步骤
}
var c = new Cat('tony', 12);
c.sayage();//打印的是12
console.log(c);//打印的是c这个对象以及name,age属性
function Dog(){
Animal.apply(this,arguments)
}
var d = new Dog('jack', 18);
console.log(d);
- 使用log代理consolg.log()
function log(){
console.log.apply(console, arguments);
}
log(d);//d为上个例子的实例
08 bind方法的用法 (函数柯里化)
var obj = {
x:1
}
function fn(y){
return this.x + y;//如果不绑定 this指向window
}
var fn2 = fn.bind(obj);//绑定后this指向obj
console.log(fn2(3));//4
//常见的函数式编程技术- 函数柯里化
function getConfig(size, color,otherOptions){
console.log(size,color,otherOptions);
}
var defaultConfig = getConfig.bind(null, 1024*768, '#f0f0f0');
defaultConfig('123');//1024*768 '#f0f0f0' 123
defaultConfig('456');//1024*768 '#f0f0f0' 456