一份须要你补充完整的函数导图!我仍是一个初学者,这篇文章是我所知道的全部关于函数的知识,若有不完善或者错误,但愿可以在评论下方指出,哈哈哈,大神勿喷。
java
查看原图react
在 JavaScript 中函数是第一类型的对象(函数是对象),咱们能够将函数视为任何类型的 JavaScript 对象;git
- 函数能够拥有有属性
Function.prototype 或者 Function.arguments...
github
- 函数能够拥有方法
Function.prototype.apply() , Function.prototype.call()Function.prototype.bind()...
编程
- 函数能够赋值给变量,数组或者其余对象属性给变量
var large=function (){}
var obj={
large:function(){}
}
复制代码
- 函数还能被调用
function large(){},large();
复制代码
- 固然函数还享有普通对象所拥有的特性,由于
Function
继承Object
- 函数能够做为参数传递给函数,(函数名自己是变量,因此函数也能够做为值来使用;便可以把函数做为参数传递给另外一个函数,也能够把函数做为另外一函数的结果返回;)
function add(a,b){
return a+b
}
function sum(fn,c){
return fn+c
}
sum(add(2,3),4);//9
复制代码
- 函数能够做为返回值进行返回
function add(a,b){
return a+b;
}
add(2,3)//5
复制代码
因此说函数是第一类型对象,函数是代码执行的主要模块单元化segmentfault
所谓的编程,就是将一组需求分解成一组函数与数据结构的技能数组
函数名是指向函数对象的指针。若是没有函数名,咱们就称之为匿名函数,匿名函数没有指向函数对象的指针,通常状况下咱们会当即执行函数,或者将匿名函数赋值给变量;浏览器
函数建立的两种方式:函数声明和函数表达式(匿名函数,拉姆达函数) bash
其中num1
和 num2
是函数的形参,(形参,形式上的参数)当 num1
和num2
做为具体的数据传递给函数时,就是实参,(实参,实际的参数) 形参和实参微信
若是形参个数大于实参个数,剩下没有对应的形参将赋值为
undefined
若是形参个数小于实参个数,多余的实参将会自动忽略
函数声明和函数表达式的区别:
咱们能够将表达式视为一个匿名函数,而后将其赋值给变量
- 解析器会率先读取函数声明,并在执行任何代码以前能够访问;函数表达式必须等到解析器执行到他所造的代码才会真正被解析(函数声明会提早;函数表达式不会);
- 函数声明后面不能跟圆括号;表达式能够(表达式后加圆括号表示函数调用);
- 函数声明只能建立局部函数;函数表达式可建立全局函数
在函数体内,变量声明的做用域开始于声明的地方,结束于所在函数的结尾,与代码嵌套无关;(即函数的做用域以及全部的变量都会在函数执行完之后当即被销毁)
命名函数的做用域是指声明该函数的整个函数范围,与代码嵌套无关
inner 函数可以访问到 outer 里面的变量,此时就造成了闭包,稍后会对闭包进行进一步了解
函数调用都会传递两个隐式的参数: this
和 arguments
;
arguments
传递给函数的全部参数集合,一个类数组结构
this
调用上下文,在哪调用,this
就指向谁,而不是取决于声明的时候。(有两个特殊的匿名函数和定时器的 this
指向 window
没有名字的函数都称匿名函数,全部的函数表达式都属于匿名函数,当即调用函数也是匿名函数
(function(c){
return console.log(c);
})(10)
复制代码
JavaScript没有块级做用域,咱们经常使用匿名函数模仿块级做用域;
for (var i=0;i<10;i++){
(function(j){
console.log(j)
})(i)
}
复制代码
匿名函数在实际项目中用的也算比较多
函数本身调用本身(引用自身),而且有终止条件
function num(n){
return num>1?(num-1)*num:1;
}
复制代码
var ninja={
chirp:function(n){
return n>1?ninja.chirp(n-1)*n:1
}
}
复制代码
当咱们在方法中递归采用了匿名函数的时候,会引来另一个问题,引用丢失;
var ninja={
chirp:function(n){
return n>1?ninja.chirp(n-1)*n:1;
}
}
var sarural={chirp:ninja.chirp};
var ninja={};
console.log(sarural.chirp(4));//报错
复制代码
var ninja1={
chirp:function signal(n){
return n>1?signal(n-1)*n:1;
}
}
var sarural1={chirp:ninja1.chirp};
console.log(sarural1.chirp(4));
var ninja1={};
console.log(sarural1.chirp(4));//24
复制代码
咱们在函数内部不适用匿名函数就能解决问题啦! 每一个函数对象在建立时也随配有一个prototype属性,它的值拥有一个constructor属性且值即为该函数的对象
回调函数:回调函数就是先定义一个函数稍后执行,不论是在浏览器仍是其余地方执行,咱们都称之为回调函数;也有种说法:回调函数是一个函数在另外一个函数中调用
有没有发现回调函数在咱们写代码的时候到处可见,回调已经成为 JavaScript 中必不可少的一部分了,咱们普遍使用回调函数做为事件处理程序
function add(a,b){
return a+b
}
function sum(fn,c){
return fn+c
}
sum(add(2,3),4);//9
复制代码
咱们首先定义了一个 add 函数,而后在 sum 中调用了他,虽然这个例子不实用,可是很好的解释了回调函数的概念
一个直接或者间接的调用自身的一种函数;他把一个问题分解为一组类似的子问题,每一个都用一个寻常解去解决;(调用自身去解决她的子问题);
递归函数能够很是高效的操做树形结构;
一句话归纳就是:一个函数可以访问该函数之外的变量就造成了闭包;
闭包记住的是变量的引用,而不是闭包建立时刻该变量的值
<script>
var num=1;
function outerFunction(){
return num;
}
outerFunction()
</script>
复制代码
<script>
var outerValue='ninja';
var later;
function outerFunction(){
var innerValue='samurai';
function innerFunction(){
console.log(innerValue);
console.log(outerValue);
}
later=innerFunction;
}
outerFunction()
later();
</script>
复制代码
在外部函数 outerFunction
执行之后 ,内部函数 innerFunction
的引用复制到全局引用later
,由于内部函数 innerFunction
引用复制到全局变量later,因此内部函数一直存在,造成了闭包;
若是直接去调用 later
则会报错,由于内部函数 innerFunction
的尚未引用复制到全局变量 later
上
只要内部函数 innerFunction
一直存在,就造成了闭包,该函数引用的变量(innerValue
,outerValue
)就一直存在,没有被 javaScript 的回收机制给回收,闭包就想保护罩同样把她们保护起来,不容许外部访问,也不能被回收机制回收
问题:闭包保存的是整个变量对象,而不是某个特殊的变量;由于闭包必须维护额外的做用域,所以会比其余函数占用更多的内存,对性能有必定的影响,所以慎重使用闭包;
私有变量:任何在函数中定义的变量,均可以认为是私有变量;由于函数的外部不能访问这些变量,私有变量包括函数的参数,局部变量,函数内部定义的其余函数
function Private(){
var num=1;
this.getnum=function(){
return num;
};
this.setnum=function(){
num++;
console.log(num);
}
}
var private=new Private();
console.log(private.num);//报错,闭包造成私有变量,访问不到
console.log(private.getnum());//可以存取方法来获取私有变量,可是不能直接访问私有变量
console.log(private.setnum());
复制代码
特权方法:有权访问私有变量和私有函数的公共方法;利用私有和特权成员,能够隐藏那些不该该被直接修改的数据
原生函数:String(),Number(),Boolean(),Array(),Object(),Function(),RegExp(),Date(),Error(),Symbol(); 原生函数能够直接当作构造函数来使用;构造函数建立出来的是封装了基本类型的值的封装对象
- Function.prototype.apply():在一个对象的上下文中应用另外一个对象的方法;参数可以以数组形式传入。
- Function.prototype.bind():bind()方法会建立一个新函数,称为绑定函数.当调用这个绑定函数时,绑定函数会以建立它时传入 bind()方法的第一个参数做为 this,传入 bind()方法的第二个以及之后的参数加上绑定函数运行时自己的参数按照顺序做为原函数的参数来调用原函数.
- Function.prototype.call() :在一个对象的上下文中应用另外一个对象的方法;参数可以以列表形式传入。
JavaScript 的四种调用形式:普通函数调用,方法调用,构造器调用模式,bind调用模式
- 普通函数调用
function add(num1,num2){
console.log(this)
return num1+num2;
}
add(2,4);
复制代码
若是使用非严格模式,this默认指向全局对象(window);严格模式(strict mode),则不能将全局对象用于默认绑定,所以this会绑定到undefined;
方法调用 当一个函数被保存为对象的一个属性时,咱们称它为一个方法,this被绑定到该对象(也有意外的状况;有时this会丢掉的对象,回调函数会修改this)
var ninja={
chirp:function(n){
return n>1?this.chirp(n-1)*n:1;
}
}
var sarural={chirp:ninja.chirp};
console.log(sarural.chirp(4));
复制代码
构造器调用
function Ninja(a){
this.a=a;
}
var ninja=new Ninja('a');
ninja.a;
复制代码
建立(构造)一个全新的对象
这个新对象被执行[[Prototype]]连接
这个新对象绑定到函数调用的this
若是函数没有返回其余对象,那么new表达式中的函数会自动返回这个新对象
apply()
,call()
,bind()
调用模式apply()
,call()
,bind()
直接将this
,绑定成一个固定的值
var tim = {
name: 'tim',
age: 20,
getName: function() {
console.log(this.name);
return this.name;
}
}
var jake = { name: 'jake', age: 20 }
tim.getName(); // tim
// jake对象没有getName方法,可是能够经过call/apply去使用tim对象的getName方法
tim.getName.call(jake); // jake
tim.getName.apply(jake); // jake
复制代码
return语句可用来使函数提早返回,当return被执行时,函数当即返回而再也不执行余下的语句;
原文连接 ,最近弄了我的微信公众号:sunseekers,有兴趣能够关注哈哈哈哈