初识函数

函数数据类型

定义函数的几种方法

1、函数声明(使用function语句来创建一个函数)

functiona,b){return a+b;};

2、函数表达式,又叫函数字面量

var fn=functiona,b){return a+b;};

这两种方式的区别:解析器会先读取函数声明,并使其在执行任何代码之前都可以被访问,而函数表达式则需要解析器执行到他所在的代码才会被真正的解释执行(主要原因js代码的变量提升导致的,在变量提升是带var和function关键字的执行分为两种情况了)

3、构造函数法

 function Person() {
 .......
  }
  var p1= new Person();

注意参数必须加引号

var sum3=new Function('n1','n2','return n1+n2');
console.log(sum3(2,3));
//输出结果为5

ps:从技术角度讲,这是一个函数表达式。一般不推荐用这种方法定义函数,因为这种语法会导致解析两次代码(第一次是解析常规ECMAScript代码,第二次是解析传入构造函数中的字符串),从而影响性能。

构造函数

1、普通函数

function Person() {
    }
    Person();

函数执行:preson不是类,他仅仅是一个普通的函数

2、 构造函数

function Person() {
 .....
  }
  var p1= new Person();
    console.log(p1);
  /*new Person()
1、把Person变成一个类:类都是函数数据类型的(包含内置类)
2、把Person当成一个普通的方法来执行
3、p1就是当前类的实例,实例都是对象数据类型的*/

Person函数(构造函数)执行过程

1.形成一个私有作用域
2.形参赋值和变量提升
3.(构造)浏览器会默认的在这个作用于中开辟一个堆内存(对象数据类型的值),然后把这个对象作为函数执行的主体(this)这个对象就是当前这个类的一个实例
4.js代码自上而下执行
5.(构造)即使我们不写return,浏览器会默认返回一个结果,返回的结果就是第三步创建的那个对象。=>浏览器默认创建的实例返回
构造函数执行,此时的person不是一个普普通通的函数,而是一个自定义类,而接收到的返回结果就是当前这个类的一个实例。

一般情况下,构造函数的函数名为大写(规范情况下,当然也可以不大写)

匿名函数

所谓的匿名函数就是没有名字的函数,正是因为其没有名字所以我们也没有办法找到他们,就涉及到匿名函数的调用问题了

匿名函数之自执行函数:
函数的创建和执行一起完成了,自执行函数不在进行变量提升

;(function () {
    console.log('ok'); 
})();

~function () {}();
 !function () {}();
 +function () {}();
-function () {}();

在function前面加!、+、-、~都可以将函数声明转化为函数表达式,消除了js引擎识别函数声明和函数表达式的歧义,
加()是最安全的方法,免得其他的和函数返回值进行运算

不过这样的写法有什么用呢?

答: javascript中没用私有作用域的概念,如果在多人开发的项目上,你在全局或局部作用域中声明了一些变量,可能会被其他人不小心用同名的变量给覆盖掉,
根据javascript函数作用域链的特性,可以使用这种技术可以模仿一个私有作用域,用匿名函数作为一个“容器”,
“容器”内部可以访问外部的变量,而外部环境不能访问“容器”内部的变量,
所以( function(){…} )()内部定义的变量不会和外部的变量发生冲突,俗称“匿名包裹器”或“命名空间”

1、function {
函数体:我们把实现当前功能或者需要做事情的那些代码,全部放在函数体中。
}
例如:

function sum(){
}
sum() ;//把上面的方法执行而且可以执行很多次

理解函数

函数就是一个方法或者一个功能使用它能够做某些事情。例如我们可以把家里的洗衣机理解为函数,使用它可以洗衣服。
函数具有两部分:创建函数(购买了一台洗衣机)、执行函数(使用洗衣机洗衣服),只创建了但是没有执行,函数没有任何意义。
sum 指的是函数本身
sum(); 把函数执行,代表的是函数执行的结果。

创建函数

1.创建一个函数名
2.开辟一个新的内存空间(有16进制的地址),然后把函数体中实现功能的js代码按照“字符串”的格式存储在空间中(对象存储的是属性名和属性值)
3.把空间地址赋值给函数名,此时函数名就可以和函数体本身关联在一起。
函数创建不执行没有意义的原因就是:创建的时候存储的都是无意义的字符串。

函数执行

  1. 函数执行的时候会形成一个私有作用域(我的地盘我做主),保护里面的私有变量不受外界干扰,我们把这种机制叫做“闭包”。提供一个环境供函数体中的代码执行。
  2. 把创建的时候存储的字符串变成真正的js代码,在私有地盘自上而下执行。

函数的作用

(1)
1. 封装
2. 低耦合,高内聚
3. 减少代码的冗余度,提高代码的重复利用率
(2)
函数执行的时候会形成一个私有作用域(我的地盘我做主),保护里面的私有变量不受外界干扰,我们把这种机制叫做“闭包”。

形参:当我们创建一个方法实现某个功能,但是实现该功能的原材料并不清楚,只有执行这个功能的时候,让用户传递过来才知道,此时我们可以先想像洗衣机一样,提供一些入口->形参:函数的入口。

定义了形参,但是执行的时候没有给传递值,形参默认存储的值是undefined(100+undefined=NaN).

实参:`执行的时候给函数传递的值。
定义了形参,但是执行的时候没有给传递值,形参默认存储的值是undefined(100+undefined=NaN)

函数的三种角色

1、普通函数
私有作用域、形参赋值、变量提升、代码执行、返回值、arguemnts、堆栈内存的销毁问题、作用域链

2、
实例、类、instanceof、constructor、prototype、proto、原型链

3、普通对象
就把它当作一个普通的obj即可,有自己的属性名和属性值。
● name:函数名
● length:形参的个数
● prototype
proto
● …….
函数的三种角色之间没有必要的联系。

函数中常用的三种方法:
call、 apply 、bind

属于Function上定义的三中方法所有的函数数据类型值都可以调取这三中方法
作用:三种方法都是用来改变一个函数中的this关键字指向的(bind不兼容ie6-8)其余的兼容所有的浏览器。

三种常用方法的语法:

>

① 把需要操作函数中的this变为第一个实参值,(在非严格模式下),第一个实参为空或者写null或者undefined,this都是window,剩下的第一个实参是谁,this就是谁。
(严格模式下)第一个实参为空,this是undefined,其余的写谁this就是谁。

② 改变为this后,把需要操作的函数执行。
唯一的区别:call在给函数传递实参的时候是一个个传递的,而apply是放在一个数组中一起传递的(但是也相当于一个个传参)

bind的语法和call一样,但是作用不一样,bind只是提前把函数中的this改变了,但是并没有立即把函数执行,它属于预先改变this(柯里理化思想)

定时器中的应用

   window.setInterval(fn,1000);//每隔一秒执行一次fn
    window.setInterval(fn(),1000);//创建一个定时器,每隔一秒中执行fn执行的返回结果
    window.setInterval(fn.call(obj2),1000);//创建定时器的时候就把fn执行了,虽然改变了this,但是一秒后执行的是fn返回的结果
    window.setInterval(fn.bind(obj2),1000);//创建定时器的时候,提前把fn中的this设置为obj2,1秒后执行的是fn
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章