JS - 函数理解

192 阅读4分钟

01 函数的声明方式

  1. 函数的声明语句
function 函数名(函数形参){
    函数内容
}
  1. 函数表达式:将一个匿名函数赋值给一个变量
var halo = function (){}
PS:有这样一种写法
var halo = function abc(){}
如果此时直接console.log(abc);会直接报错

在函数表达式中halo为变量名称,相当于函数的实参可以在函数内调用也可在函数外调用。abc是函数名称,相当于函数的形参,只能在函数内调用

  1. Function构造函数
    new Function();
    var fn = new Function( 'x' , 'y' , 'return x+y;' ); 等同于 Function fn(x, y){ return x+y; };

02 函数的返回值

  1. 如果函数没有返回值 打印函数显示为undefined
  2. 函数内return后的语句有可能执行
    例如 try{return 0};catch(e){return 1};finally{return 2} 不论执行try还是catch语句finally都会执行
  3. 如果函数调用时在前面加上new前缀,且返回值不是一个对象,或者没有返回值,则返回该函数对象(this)
function fn(){
    return 1;
}
var test = new fn();
console.log(test);//返回的是整个fn函数

如果返回值是一个对象 则返回该对象

03 函数的调用

  1. 函数调用模式
function add(x,y){
    return x + y;
}
var sum =add(3,4);
  1. 方法调用模式
var obj = {
    //fn为obj对象的方法
    fn:function(){
        console.log('函数内容');
    }
}
obj.fn();
  1. 构造函数调用模式
function fn() {
      return 1;
    }
var test = new fn();
console.log(test);
  1. 间接调用模式 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 函数的参数

  1. 函数传递进来的参数没有限制 可以不传参数 可以穿任意数据类型的参数 可以传多个参数(函数的形参只有一个)
  2. 同名形参 在非严格模式下
function fn(x,x,x){
    return x;
}
console.log(fn(1,2,3));
//此时打印出来的是3 严格模式下报错
  1. 参数个数
//实参比形参数量少
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 函数属性

  1. length属性 形参的个数
  2. arguments属性 实参的个数
function add(x,y){
    console.log(argunments.length);//4
    console.log(add.length);//2
}
add(1,2,3,4);
  1. name属性 当前函数的名字
var fn = function(){};
console.log(fn.name);//fn
var fn2 = function aaa(){};
console.log(fn2.name);//aaa
  1. prototype属性 (后面有讲解)
function fn(){}
console.log(fn.prototype);//打印一个对象 该对象为fn的原型(父级)对象

07 函数call()、apply()方法使用

  1. 找出数组最大元素
var arr = [4, 8, 23 ,1 ,66 ,2];
var max = Math.max.apply(null, arr);//null在非严格模式下指向window
console.log(max);//66
  1. 将类数组(argument)转化成数组
function add(){
    var arr = Array.prototype.slice.apply(arguments);
    ///Array.prototype为add的原型对象 slice方法为截取数组值的方式
    //将arguments类数组转化为数组的原因是类数组有许多数组的方法不能调用
}
add(1,2,3);
  1. 数组追加
var arr = [];
Array.prototype.push.apply(arr,[1,2,3,4]);//arr=[1,2,3,4]
  1. 利用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);
  1. 使用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