JavaScript特殊的对象2:函数

1、为何说函数是特殊的“对象”呢?

1. 由于函数能够经过Function()构造函数来定义:var f = new Function("x","y","return x*y;");java

2. 函数属性:闭包

1)length(形参个数)app

2)prototype:每一个函数都有这个属性!(引用)指向一个(原型)对象。每一个函数都会有,构造函数也有。因此用构造函数去建立对象的时候,这个对象的原型是 构造函数.prototype这个属性的值。(这里边构造函数是对这个属性作个赋值了的)函数

3. 函数方法:函数对象的两个方法call()和apply();spa

2、函数的定义

1. 函数声明语句

function f(x){}这个是函数声明语句,它其实是声明了一个变量f,并把一个函数对象:{} 赋值给它!
1) 这句话定义了一个变量名为f。并给它赋值(即指向函数体{}):这个定义建立了一个函数对象,并将其赋值给变量f。函数的名字其实是可不见的,f仅仅是一个变量名而已,这个变量名指向(引用)函数对象。
2)无论这个函数声明放在哪里,它在整个脚本全局域里均可见。由于这里有提高的机制在里面:函数名和函数体(赋值)均被提早到(顶部)。
这也是为何能够调用本身的缘由了。 
3) 不一样于变量提高,变量提高只是把声明提高,可是赋值定义却没有提高。
4.)函数声明语句非真语句。不能插在任何语句之中。而函数定义表达式能够出如今任何地方,由于他们自带;分号本身自己就是语句了。.net

2. 函数表达式(匿名函数方式)

var f = function(x){};这是函数表达式(原始)
1)若是在这个表达式以前调用了f(x);会报错。由于只提高了变量f的声明,变量的赋值初始化也就是绑定函数对象没有被提高,因此f仍是个undefined,还不具有函数性质。
2)当函数表达式加上了名称  var a = function f(x){};实际上函数的名称f将成为函数内部的一个局部变量。prototype

3)function(x){}就是一个匿名函数那它怎么调用呢?对象

A. 若是这里,把他赋值给 f 。这样f就能去引用它。因此咱们能够直接用f(x)进行调用。blog

B. 自调用。把匿名函数整改放在这样的表达式括号里();并在这个表达式括号中匿名函数的尾部加上()就是自调用。(function(x){..}(3)); 或者(function(x){..})(3);继承

C. 匿名函数最大的用途是建立闭包(这是JavaScript语言的特性之一),而且还能够构建命名空间,以减小全局变量的使用。

3. 构造函数的方式

var f = new Function("x","y","return x*y;");

4. 当一个函数定义以后JavaScript会自动给这个函数的原型添加一个constructor属性并并赋值这个函数的类。

3、函数调用

默认是undefined,若是有return something 就返回具体值,没有return 也是undefined。

1. 自调用 (function(){}());——》b=function(){} ——》(b());——》b();

2. 

4、特殊函数

1. 构造函数(类)

首先第一个概念:类 就是构造函数,构造函数就是类  //不是java里面的类里面有构造函数。
var F = function(){};
var obj = New Object();
F.prototype = obj; //继承其余类
F.prototype.construtor = F;
//如今添加本身的
F.prototype.x = function(){...};
F.prototype.y = function(){...};
var f = new F();
f.construtor ——》F.prototype.construtor = F ——》f.construtor = F;
f.prototype = Object() 另外f还有自有属性  x 和 y。

当不继承任何人时
能够是

var F = function(){....};
var f = New F();
F.prototype = {....} = f;
F.prototype.construtor = F;
F.prototype = f
f.construtor= F

2. 匿名函数与自调用

匿名匿名就是没有名字的函数定义:function(){};

自调用:(function(){}());或者(function(){})();

 

2. 工厂函数

5、闭包和做用域链概念

1.  做用域链

1)首先咱们从全局出发<script>中,其实就是一个全局函数变量(若是C的main()函数同样),咱们在其中定义的全部Function定义的函数(它里面也有可能嵌套)也都是嵌套在这个全局函数而已,因此整个js代码咱们能够从某种程度上当作一系列的函数嵌套过程。既然有嵌套,随之就是有嵌套深度,那,怎么表现这个深度呢,咱们这里就能够用(函数对象)做用域链来表示。记住js和其余语言不一样,不是块做用域,而是函数做用域。这条做用域上保存这个这些嵌套的函数对象,咱们能够定义全局函数对象在做用域链中是第1层,随着嵌套依次叠加。

2)函数调用时做用域链起到的做用:

做用域链在函数定义的时候决定的(也就是在定义这个函数的时候它的做用域随之肯定,函数被绑定在上面)。调用时依赖这个做用域,因此什么时候何地调用,它只会在这个做用域里去找它须要的变量。若是函数定义是变量就在这个做用域上,它就跑不掉了(闭包)。就好像,一个家谱(做用域链)同样,(函数)你生下来,就被写进了一个家谱,无论你身在何方,中国仍是美国,你什么时候何地均可以(打电话)问家里(问爸妈问爷爷奶奶)要钱(变量)。可是不能跟同级的姐妹或者本身的子女要。

当函数调用须要找变量时,从自身出发(做用域链最高层)开始找,若是本身有了,就拿,没有就会沿着做用域链一层层往下找,直到第0层(全局函数变量)为止。

3)变量提高定义是在函数体内的声明的全部变量在函数体内任何地方都是可见的。按照正常的习惯咱们如今函数顶部先var声明好变量并定义好,可是有些“变量”比较调皮,没有var声明变量以前,它先在前面直接使用,可是后面它又想起来了,在函数后面补上var 并赋值。这是能够的,由于js的规则是在所用函数执行以前,把全部变量的声明都统一提高到函数顶部。(虽然js帮忙提高,也就只是声明提高,咱们知道只声明不赋值的变量是undefined,因此前面引用的那个会是undefined但若是没有var声明但赋值了,后面又追加声明,它但是拿到赋值的值。只有在真正他想起来赋值的地方,这个变量才算真正有意义)。

2. 闭包

1)(从全局开始一直嵌套)的全部函数对象能够经过做用域链相互关联起来,函数体内部的变量均可以保存在做用域内叫闭包。若是函数定义是变量就在某个做用域上,它就跑不掉了。什么时候何地调用函数,它都能在本身相应的做用域链上找到本身所须要的变量。这个就是闭包在js中起到的做用。

 

1. 在函数中定义里一个局部变量a和一个嵌套函数f()绑定在一块儿,无论在什么时候何地只要能调用到f(),就必定用到这个变量a。这样的a变量咱们能够叫私有变量。
2. 如何把两个闭包放在一个做用域中,而后能共享一样的私有变量?

7、call()和apply()和bind()(点击可查看)

相关文章
相关标签/搜索