javascrpt的函数细节,匿名函数

正常函数:

function a (i,j){

  return i+j;

}

 

匿名函数:建议在最外面加上一对圆括号,目的是把函数当成表达式

(function (i,j){

  return i + j

})  //只完成了定义,没有调用它

 

匿名函数调用

(function (i,j){

  return i + j

})(1,2)  //那么匿名函数没有函数名,怎么调用呢,后面加上圆括号直接传参调用

 

匿名函数还可以作为其他对象的函数:

doucument.getElementById("ID").onclick = (function (){ console.log('你点击了我!');});

匿名函数简化写法:箭头函数

(参数) => {

  return 结果;

}

如果只有一个参数,那么()可以省略:

参数1 =>{

  return 结果;

}

 

如果函数体内只有一行代码,那么{} 可以省略:

doucument.getElementById("ID").onclick = (参数1) => consle.log('你点击了我!');

javascript中的函数本质上是一个对象,所以可以做赋值操作:

doucument.getElementById("ID").onclick = 函数名或者函数体定义

对象有属性,有方法,可以作为参数传递,可以是另外函数的返回值,非常灵活!

使用 console.dir(函数名),可以看到函数(即对象)内部定义的属性和方法

作为方法参数传递:

function a(){
  console.log()
}

function b(fn){
  console.log();
  fn(); // 既然fn是从外面传递进来的一个函数对象,那么加上()就可以直接调用它
}

b(a);

可以作为函数返回值:

function c(){
  console.log("c");
  function d(){
     console.log("d");     
  }
  return d;  //返回d的对象定义,并不是返回d的执行结果,所以不会打印d  
}

c()(); //既然返回的是函数定义,那么再加一个()即是调用d函数

函数的作用域:

如果用console.dir(函数名),可以输出函数中的内置属性(js中的函数被当成对象看待),其中用[[....]]双中括号标识的是内置属性,不能调用但是可以查看[[Scopes]]代表的就是该函数的作用域,这里不显示函数体内的作用域,只显示父和全局级的作用域,如下图:closure(a){y:20}就是父作用域,而Global就代表全局作用域,这两个作用域都是函数可以读取的。

 函数的闭包:闭包就是指函数可以访问自己的作用域中的变量,即使函数被传递到别的地方,也依然可以访问,因为函数在定义的时候作用域已经确定了,如上所述可以查看作用域,那么下图闭包可以正常打印x,y的值吗?答案是可以。

 

 let和var作用域:

如果函数外层引用的是let变量,那么外层普通的{}也会作为作用域边界,最外层的let 也占一个script作用域

let x=10;

if(true){
     let y = 20;
     function(){
          console.log(x,y)

     }   
        
      console.dir(b);
}

 

如上图:红色框的是自己的作用域,不在讨论之列;

绿框的是Block作用域,界定的关键是{},y=20;

蓝框的是script作用域,x=10

最后黄色框的是Global全局作用域

dir()打印如下图:

 

 如果同样的代码,换成var声明,那么只有Global作用域了,蓝框显示,XY都属于Global作用域,也就是说如果换var声明,那么外层普通的{}不会视为边界

 

 查看该函数作用域,如下图

 

代码 如下:

// 案例1:

var e=10;
if(true){
   var e=20; //与外面的e视为同一个作用域的同一个变量,20将替代10赋值
   console.log(e);   //输出20 
}
console.log(e); //输出20

// 案例2:

let e=10;
if(true){ //{}被视为作用域边界
   let e=20; //用let声明,与外面的e不是同一个变量
   console.log(e);   //输出20 
}
console.log(e); //输出10

// 案例3:如果用var要把里、外的作用域分开,那么就需要使用到函数
var e=10;
if(true){
  function b(){
     var e=20; 
     console.log(e);   //输出20 
  }
  b();
}
console.log(e); //输出10


 预解析机制:https://www.bilibili.com/video/BV15T411j7pJ/?p=39&vd_source=9752cdd43d8570cd76479220c765bc34

 

用var声明的变量和用function声明的函数,都会在预编译阶段放到script标签下面,这就是声明提升。(这个跟作用域有关系吗?)

//案例一:将声明的变量提升到script标签下面,因为只是提升了声明的部分到script标签下面,没有赋值值
console.log(myname) //打印undefind
var myname ="11"
console.log(myname) //打印11

//案例二:赋值型函数

myFunc() //打印错误信息,myFunc不是函数,因为只是提升了声明的部分到script标签下面,没有赋值给他函数的部分,但是如果调用的是一个没有声明的函数,比如func2,那么就会报错此函数未定义,区别就在于预编译阶段是否有找到此函数名
var myFunc = function(){
  console.log("11")    
}
myFunc() //打印11

//案例三:声明型函数

test() //不报错,打印11,声明式函数将整个方法体提升到script标签下面,所以在任何地方都可以调用,不一定要在方法定义之后调用

function test(){  console.log("11")}

test() //不报错,打印11

 

posted @ 2022-09-19 10:25  卡吧不死机  阅读(88)  评论(0编辑  收藏  举报