当前位置: 首页 > 新闻动态 > 猜您喜欢 >

前端必备之函数

作者:深圳纯量网络 阅读: 发布时间:2024-08-17 06:00

摘要:为什么把函数(function)放在最开头写?因为函数是JavaScript世界里第一等公民,在这个世界里到处都是函数;而函数带有一个特别重要的...

只有声明形态的函数,才具有提升的特性。

何为“提升”?所谓提升,意思就是代码的执行顺序提升排到最前面。

console.log(func0); //>> func0() {return 0}
console.log(func1); //>> undefined
//函数的声明形态
function func0() {
  return 0;
}
//函数的表达式形态
var func1 = function() {
  return 1;
};

上面的代码func0函数在声明之前就可以调用console.log(func0)被打印输出,是因为JS引擎把声明形态的函数提前处理,相当于提升了处理优先级。上面代码等同于:

//函数的声明形态
function func0() {
  return 0;
}
console.log(func0); //>> func0() {return 0}
console.log(func1); //>> undefined
//函数的表达式形态
var func1 = function() {
  return 1;
};

三、IIFE与匿名函数、有名函数

还有一种叫 IIFE(Immediately-Invoked Function Expression,立即执行函数)形式的函数调用方式,非常适合匿名函数调用,特征是在关键字function左侧有一个括号“(”,右侧的闭括号“)”则有两种放置方式,一种是放在紧挨调用括号对的左侧,一种是放在紧挨调用括号对的右侧。如下代码示例,这两种写法是等效的,都可以。

(function(){
    console.log("我是立即运行的匿名函数");
})();
(function(){
    console.log("我也是立即运行的匿名函数");
}());

既然匿名函数加上IIFE让代码这么简洁,为什么还需要给函数起名——有名函数呢?

首先,最好的理由之一当然是为了方便递归,递归需要函数调用自身,函数如果没有名字,就无法有效地通过一个标志符(名字)找到函数自身以便供调用。函数的名字可以通过 name 属性读取到。

//函数调用自身称为递归,函数名为“func”
(function func(i){
    console.log("函数名为"+func.name+",第"+i+"次调用")
    if(i<3){//递归出口
        func(++i);//递归
    }
})(1);
//>> 函数名为func,第1次调用
//>> 函数名为func,第3次调用
//>> 函数名为func,第3次调用

其次,匿名函数不利于调试栈跟踪,有名函数根据名字可以很快在调试的时候定位代码位置。

最后,匿名函数看起来有点那么不直观。当然使用熟悉之后会相当直观,本书会大量使用IIFE。

前端必备函数有哪些_前端必备函数是什么_

四、匿名函数真的没办法实现递归调用自身吗?有!

每个函数都有个 arguments 属性,代表函数参数的集合,该集合又有一个方法叫 callee,代表函数本身,这样就可以通过 arguments.callee() 调用了自身了。//函数调用自身称为递归,函数名为“func”

(function (i){
    console.log("函数名为"+func.name+",第"+i+"次调用")
    if(i<3){//递归出口
        arguments.callee(++i);
    }
})(1);
//>> 函数名为func,第1次调用
//>> 函数名为func,第3次调用
//>> 函数名为func,第3次调用

在严格模式下,第5版 ECMAScript (ES5) 已经禁止使用 arguments.callee()。当一个函数必须调用自身的时候,不推荐使用 arguments.callee(),尽量通过函数命名然后通过该名字调用自身。

在代码任意行输入字符串"use strict"可以开启严格模式。

五、定义作用域

在ES6之前,JavaScript没有块级作用域,只有函数作用域的说法,也即函数比较像java语言里面的大括号对 “{ }”,能定义变量可见的区域——作用域。在ES6出现之后,JavaScript才有了块级作用域,通过 let 关键字实现。

六、箭头函数

用(参数) => { 表达式 }这种写法声明一个函数,就叫箭头函数(也叫lamda表达式)。箭头函数是ES6带给我们的语法糖之一,主要意图是定义轻量级的内联回调函数,当然最直观的好处是可以少敲几个字符。如下代码,用function关键字声明一个匿名函数,和用箭头=>声明函数是等效的。

(function(i){
    console.log(i);
})(1);
((i)=>{
    console.log(i);
})(1);

箭头函数不暴露aguments对象,所以,如访问arguments,将会当做一个普通变量进行访问。

((a)=>{
    console.log(a);//>> 1
    
    console.log(arguments.length);//>> Uncaught ReferenceError: arguments is not defined
})(1);

箭头函数一个明显作用就是可以保持this的指向,总是指向定义它时所在的上下文环境。

最后,箭头函数也没有自己的 super或new.target。

前端必备函数是什么__前端必备函数有哪些

七、高阶函数

如果某个函数可以接收另一个函数作为参数,该函数就称之为高阶函数。

函数作为参数?这似乎太奇怪了。其实是因为在JavaScript里函数可以赋值给某一个变量,而变量可以作为参数传递给函数,因此函数也可以作为参数传递给函数。

高阶函数最常见的形式之一就是回调函数。

function fn1(callback){
    if(callback){
        callback();
    }
}
fn1(function(){
    console.log("高阶函数");//>> 高阶函数
});

另外,高阶函数源自于函数式编程

八、函数重载

重载是面向对象编程语言(比如Java、C#)里的特性,JavaScript语言并不支持该特性。所谓重载(overload),就是函数名称一样,但是随着传入的参数个数不一样,调用的逻辑或返回的结果会不一样。jQuery之父John Resig曾经提供了一个非常巧妙的思路实现重载,代码如下

(() => {//IIFE+箭头函数,把要写的代码包起来,避免影响外界,这是个好习惯
    // 当函数成为对象的一个属性的时候,可以称之为该对象的方法。
  
    /**
    * object:一个对象,以便接下来给这个对象添加重载的函数(方法)
    * name:object被重载的函数(方法)名
    * fn:被添加进object参与重载的函数逻辑
    */
    function overload(object, name, fn) {
      var oldMethod = object[name];//存放旧函数,本办法灵魂所在,将多个fn串联起来
      object[name] = function() {
        // fn.length为fn定义时的参数个数,arguments.length为重载方法被调用时的参数个数
        if (fn.length === arguments.length) {//若参数个数匹配上
          return fn.apply(this, arguments);//就调用指定的函数fn
        } else if (typeof oldMethod === "function") {//若参数个数不匹配
          return oldMethod.apply(this, arguments);//就调旧函数
                                                  //注意:当多次调用overload()时,旧函数中
                                                  //又有旧函数,层层嵌套,递归地执行if..else
                                                  //判断,直到找到参数个数匹配的fn
        }
      };
    }
  
    // 不传参数时
    function fn0() {
      return "no param";
    }
    // 传1个参数
    function fn1(param1) {
      return "1 param:" + param1;
    }
    // 传两个参数时,返回param1和param2都匹配的name
    function fn2(param1, param2) {
      return "2 param:" + [param1, param2];
    }
  
    let obj = {};//定义一个对象,以便接下来给它的方法进行重载
    
    overload(obj, "fn", fn0);//给obj添加第1个重载的函数
    overload(obj, "fn", fn1);//给obj添加第2个重载的函数
    overload(obj, "fn", fn2);//给obj添加第3个重载的函数
  
    console.log(obj.fn());//>> no param
    console.log(obj.fn(1));//>> 1 param:1
    console.log(obj.fn(1, 2));//>> 2 param:1,2
})();

  • 原标题:前端必备之函数

  • 本文由深圳纯量网络小编,整理排版发布,转载请注明出处。部分文章图片来源于网络,如有侵权,请与纯量网络联系删除。
  • 微信二维码

    CLWL6868

    长按复制微信号,添加好友

    微信联系

    在线咨询

    点击这里给我发消息QQ客服专员

    点击这里给我发消息电话客服专员

    在线咨询

    免费通话


    24h咨询☎️:132-5572-7217


    🔺🔺 24小时客服热线电话 🔺🔺

    免费通话
    返回顶部