JavaScript笔记: 函数的应用

JavaScript 中函数的应用十分的广泛,如果你仔细研究过JQuery等库的话,你会发现
基本JQuery所提供的库,都是可以接收一个函数作为传入参数,达到更灵活的目的。

0x00 函数的主要用途

在JS中,函数的用途无外乎以下集中:

  1. 作为函数调用
  2. 作为方法调用
  3. 作为构造器调用
  4. 指定上下文调用

作为函数和方法调用的,是比较熟悉的。如果直接定义的情况下,我们认为是做为函数调用,而将一个函数具体赋给了一个对象后,我们称之为做为方法调用。

但是,这二者之间的区别是可以被模糊掉的。例如,我们在全局环境下声明一个函数,其实是可以看作是在window对象上面定义了一个方法。因为从上下文的角度来讲,函数的的上下文
是不可或缺的。因此,一个函数调用,其实就是一个赋予它上下文执行的过程。

作为构造器调用的过程,其实就是用一个函数声称一个对象。这个函数的额作用就是返回一个对象。如下面的一个构造器:

function Person() {
    this.age = 22;
    this.say = function() {
        return "hello";
    };
}

var p1 = new Person();

这里特别的就是 new 关键字,这关键字其实就是创建一个空对象,将这个空对象作为函数的上下文传递给函数,如果没有显示的返回值,则将此对象返回。这点,有过其他面向对
象编程经验的,自然不言自明。

指定上下文的调用的过程,就是用到了函数的两个重要方法,apply()call()这两个方法的作用是一样的,都是给函数指定一个上下文,然后调用它。这种机制,在很多支持事件回
调的函数中,都可以看到。

0x01 匿名函数

匿名函数 顾名思义,就是没有名字的函数。我们来看两种函数的声明定义:

function foo1() {
    return "123";
}

var foo2 = function() {
    return "456";
};

foo1();
foo2();

这两种看起来没有什么太大的差异,但是如果你直接通过函数名调用,你会发现不一样的结果:

>foo1
< function foo1(){...};
>foo2
< function(){...};

第二个函数的用法,就称之为匿名函数。他没有直接给于一个名字,就是没有直接给定上下文。而是通过赋值给某个变量,对象的属性,来指定一个匿名函数上下文。而有名函数的声明过
程,就是在上下文中绑定了一个这个函数名的属性。上例子中,我们可以通
window调用也是一样的:

window.foo1

0x02 即时函数

有经验的老司机同志,一定见过这样的函数调用方式:

(function(){})();

而这样的一行代码,就可以将一个函数执行。这里特别注意的是两个括号,可以精剪为:

(...)();

第一个括号的,接收的是一个函数,可以是一个匿名函数,也可以是一个已经声明的函数的名字或者调用。第二个括号里面标识的是注入参数,即我们在第一个括号中的函数的参数,可以
通过第二个括号来注入。如:

(function(a,b) {
    return a+b;
})(1,2);
// out 3

这段代码的作用其实就是如下的四个步骤:

  1. 创建一个函数实例
  2. 执行该函数
  3. 销毁该函数(应为没有引用这个函数的引用了)

题,完成之后,便可以销毁,避免了全局环境被污染的问题。

看下面这段代码:

(function(app) {
  app.AppComponent =
    ng.core.Component({
      selector: 'my-app',
      template: '<h1>My First Angular 2 App</h1>'
    })
    .Class({
      constructor: function() {}
    });
})(window.app || (window.app = {}));

灵活的控制全局环境的生成。

0x03 递归函数

递归是需要结果很多重复操作的选择,性能方面的我们暂且不说,但是从另一个角度来说
,至少代码
够简练。但是,如果没遇到一种情况:

obj.foo = function(){};

我们要在这个函数的内部,进行递归调用,诚然我们直接通过在方法的内部调用:

obj.foo = function(){
    obj.foo();
};

这样的方式,在这个函数的上下文没有被改动的情况下,是可行的。当然我们进一步,采
this

obj.foo = function(){
    this.foo();
};

这样的情况,要求每个调用的这个函数的方法属性都叫做foo,万一名字变了,又是个
坑了。那么,
其实JavaScript支持一种内连函数的声明方式,如下:

obj.foo = function a(){
    a();
};

给了函数一个名字,就不再是匿名函数了,即时是上下文和调用名字变了,依然可以安心的递归下去。

注意:值得注意的是,函数的arguments对象中,有一个叫callee的属性,这个
属性就是用来指代函数本身的,不过这个函数是有名还是匿名。但是这个属性有被取消的
趋势,并且在严格模式下已经是不可用的了。

0x04 函数即对象?

JavaScript中,函数是作为第一型对象存在的。这既是一种函数式编程的方式,又是一
种面向对象的方式,所以很多原教旨主义者,对此十分反感。但是我认为,真是结合了
这两者形式,才是功能强大的原因。

JavaScript中,既有代表对象的原型对象Object又有代表函数的Function原型对象。函数既是对象,
或者对象既是函数,这只不过是你从不同的角度来看待这件事情罢了。

0x05 总结

JavaScript一直被处在一种被忽视的地位,因为各种库的存在,很多人执着于库,是用JQuery还是TypeScript
是用AngularJS还是React?其实,我觉得这些都可以,一个库的存在,之所以有很多人用,你说有很致命的bug,
不能说不可能,只是可能性很小。而很多人却忽视了JavaScript本身的问题。包括,google也是,angularJS2.0的版本,
更加偏向于TypeScript去了。当然,JavaScript有许多被人诟病的问题。但是,它毕竟是现在最重要的前端语言,(额...
node派请不要出来打脸),了解其被背后的机制,是作为一个程序员所必要的,如果你要使用到它的话。

JavaScript我认为最重要的几个特性,就是:

  • 函数
  • 对象
  • 正则表达式
  • 定时器

这四者之间,相互交叉那是当然的,而我认为,这四者之中,最基础的是函数。正则虽然有些不同,当在JavaScript,中正则
是属于特殊对象的范畴。在应用过程中,使用到函数的那是必不可少的。所以...

函数为基

我的blog原址:

http://yieldblog.me/2016/08/12/JavaScript%E7%AC%94%E8%AE%B0%EF%BC%9A%E5%87%BD%E6%95%B0%E7%9A%84%E5%BA%94%E7%94%A8/

推荐阅读更多精彩内容

  • 前言 人生苦多,快来 Kotlin ,快速学习Kotlin! 什么是Kotlin? Kotlin 是种静态类型编程...
    橘之缘之空阅读 17,781评论 9 108
  • 函数 函数的一些特征 函数形参类似函数内的局部变量 函数没有return语句就返回undefined 除了函数实参...
    qingyun1029阅读 185评论 0 3
  • 前期的准备工作 当总理告诉我们,想带八位同学去欧亚分享实验室的学习方法时,在某同学的鼓励下,我报了名。接下来所有人...
    葶寳寳阅读 40评论 2 2
  • 图/小久英 文/小久英 姹紫嫣红都开遍了来看看枯树吧它们也各有风情 一段没有蓝天白云的旅程,来到渡口,想到很多渡口...
    小久英阅读 343评论 9 6
  • 琐事记4.25 我有一个普通朋友在街上做生意,每次经过他的店,我总是要停下来和他聊几句天。在和我聊天的时候,他常常...
    小棕榈阅读 60评论 0 0