关于函数

一些基本概念

1.函数就是将一批重复的代码封装,以供调用;其本质就是代码块。

2.函数的name属性是一个字符串。

3.复杂的函数命名需要遵循“驼峰命名法”。

4.函数后面圆括号里面的是函数的参数,花括号里面的是函数代码块。

5.函数的参数分为形参和实参,形参是指:函数在定义时,圆括号里面的内容叫做形参,函数在调用时,圆括号里面的内容叫做实参,实参可以是变量也可以是值。

6.函数是变量的特例。(var声明一个变量,可以是7种数据类型;函数只能声明一个函数)

函数的几种声明方式

1.匿名函数

var f;
f=function(x,y){
    return x+y
}
f.name //'f'

**把一个函数给一个变量,这个函数就是一个匿名函数,这个变量就相当于一个函数,可以直接进行调用。

2.具名函数(命名函数)

function 函数名(参数){代码块}

function f (x,y){
    return x+y
}
f.name //'f'

3.具名函数赋值

var x =function y (a,b){}
console.log(y) //报错
x.name //'y'

function y (a,b){}
console.log (y) //不报错

//以上情况是由于JS的不一致

4.window.Function

var f = new Function('x','y','return x+y')
f.name //"anonymous"(匿名的)

一个小例子

n=1;
var f = new Function('x','y','return x +'n'+y')
//等价于
var f = new Function('x','y','return x +1+y')
f(1,2) //4

5.箭头函数

var f = (x,y) => {return x+y}

var f = (x,y) => x+y //{}可以与return一起去掉

var n = n => n*n //若对象只有一个参数,()可以去掉

函数调用

call

function f(x,y){
  return x+y  
}

内存图解:

**params、fbody标注为假设标注,实际不存在**

代码理解:

f.params=['x','y']
f.fbody='return x+y'
f.call=function(){
  eval (f.body)  
}
f.call()

//eval是window的全局对象
//eval(‘xxxx’)给一个字符串当代码执行

eval ('1+1')  
//2
eval ('1+"1"')
//"11"

**函数就是对象,函数的调用过程就是eval调用体的过程**

call调用与()调用,this与arguments

f (1,2) //(1,2)就是arguments
//等价于
f.call(undefined,1,2) //undefined就是this,1,2就是arguments

call的第一个参数可以用this得到,后面的参数可以用arguments得到

var f = function(){
  console.log(this);
}
f.call()//window  普通模式下若this是undefined,浏览器会将this默认变为window

function f(){
    console.log(this)
}
f.call(1)//Number 对象 1


var f = function(){
    'use strict'
  console.log(this);
}
f.call()//undefined  严格模式下若this是undefined,则为undefined

function f(){
    'use strict'
    console.log(this)
}
f.call(1)//1

//arguments  伪数组  原型链中没有Array.prototype这一环,__proto__指向的是Object.prototype,不能使用.push等属性

call stack  调用栈

function a (){
  console.log('a1')
  b.call()
  console.log(a2)
  return 'a'        
}
function b (){
  console.log('b1')
  c.call()
  console.log(b2)
  return 'b'      
}
function c (){
  console.log(c')
  return 'c'      
}
a.call()
console.log('end')

栈溢出(内存溢出)

stack overflow

(还不知道这个要怎么解决,以后遇到再说吧.. -_- ..)

关于递归

function sum (n){
  if(n==1){
  return 1  
    }  else {
        return n+sum(n-1)  
     }
}

sum = 5;//5+sum(4)
//sum (4) //4+sum(3)
//sum(3)//3+sum(2)
//sum(2)//2+sum(1)
//sum(1)

关于作用域(scope)

一些概念:

Javascript 有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。

例:

var a = 1
function f1 () {
  var a = 2
  f2.call()
  console.log(a)//2
  function f2(){
      var a=3
      console.log(a)//3
    }        
} 
f1.call()
console.log(a)//1

声明提前

var a 
function f1 () {
    var a
    a = 2
    function f2(){
        var a
        a = 3
        console.log(a)//3
    }     
   f2.call()
    console.log(a)//2
} 
a = 1

f1.call()
console.log(a) //1

 例:

var a = 1
function f1 (){
    f2.call()
    console.log(a)
    var a=2
    function f2(){
        var a=3
        console.log(a)
    }
}
f1.call()

变量提升

var a 
function f1 (){
    var a
    function f2(){
        var a
        a=3
        console.log(a) //3
    }
    f2.call()
    console.log(a) //undefined
    a=2
}
a = 1
f1.call()

例;

var a = 1
function f1(){
    console.log(a)//undefined
    var a=2
    f2.call()
}
function(){
    console.log(a)//1 作用域里面没有a,则找父作用域里面的a
}

关于闭包

若一个函数,使用了它作用域外的变量,那么(这个函数+这个变量)叫做闭包。

其作用就是让这个变量值一直保存在内存中,要使用的时候即刻可以使用,另外可以通过闭包在函数外访问函数内部。

var a=1
function f (){
  console.log(a)  
}

关于立即调用函数

声明一个函数,立即调用

使用原因:

1.全局变量不好用

2.使用局部变量,需要一个函数,在函数里声明,立即调用

3.匿名函数直接调用,会有报错

解决办法

(1)整体添加()

(2)将函数()起来再.call()调用

(3)直接再function前面加减号-或者加号+

(4)在function前面加!或~ 》》推荐《《

(5)使用代码块

 

ES6:let的作用域就是{}里面,let不会变量提升

待补充... ...

原文地址:https://www.cnblogs.com/BUBU-Sourire/p/11133142.html