JavaScript 中函数的应用十分的广泛,如果你仔细研究过JQuery等库的话,你会发现
基本JQuery所提供的库,都是可以接收一个函数作为传入参数,达到更灵活的目的。
0x00 函数的主要用途
在JS中,函数的用途无外乎以下集中:
- 作为函数调用
- 作为方法调用
- 作为构造器调用
- 指定上下文调用
作为函数和方法调用的,是比较熟悉的。如果直接定义的情况下,我们认为是做为函数调用,而将一个函数具体赋给了一个对象后,我们称之为做为方法调用。
但是,这二者之间的区别是可以被模糊掉的。例如,我们在全局环境下声明一个函数,其实是可以看作是在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
这段代码的作用其实就是如下的四个步骤:
- 创建一个函数实例
- 执行该函数
- 销毁该函数(应为没有引用这个函数的引用了)
题,完成之后,便可以销毁,避免了全局环境被污染的问题。
看下面这段代码:
(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原址: