JS-7 JS函数;声明函数;调用函数;函数表达式;JS头等函数;回调函数;高阶函数;匿名函数;立即执行函数;在Chrome进行JS调试debug;浏览器工作原理详解;浏览器调试功能介绍

1_初识JS函数

1.1_名词foo、bar、baz

foo、bar、baz这些名词:

  • 通常被用作函数、变量、文件的名词;已变成计算机编程的术语一部分;

  • 但是这些名词本身并没有特别的用途和意义;

  • 常被称之为 “伪变量”(metasyntactic variable)


1.2_函数

举例:

  • alert函数: 浏览器弹出一个弹窗

  • prompt函数: 在浏览器弹窗中接收用户的输入

  • console.log函数: 在控制台输入内容

  • String/Number/Boolean函数等……

函数是什么?

  • 函数是某段代码的封装,这段代码帮助完成某一个功能;

  • 默认情况下JavaScript引擎或者浏览器会提供一些已经实现好的函数;

  • 也可编写自己的函数;



2_函数的使用

函数的使用——两个步骤:

  • 声明函数 —— 封装 独立的功能

  • 调用函数 —— 享受 封装 的成果


2.1_声明函数

声明函数,在JS中也可以称为定义函数:

  • 声明函数的过程是对某些功能的封装过程;

  • 在开发中,会根据自己的需求定义很多自己的函数;

function 函数名(){
函数封装的代码
……
}

注意:

  • 函数名的命名规则和变量名的命名规则相同;

    • 第一个字符必须是一个字母、下划线( _ )或一个美元符号( $ )
    • 其他字符可以是字母、下划线、美元符号或数字
    • 不能使用关键字和保留字命名:
  • 函数名尽量做到见名知意(使用动词更多);

  • 函数定义完后里面的代码是不会执行的,函数必须调用才会执行;


2.2_调用函数

调用函数,也可以称为函数调用:

  • 调用函数是让已存在的为己所用;

  • 这些函数可以是刚刚封装好的某个功能函数;

  • 也可以使用默认提供的或者其他三方库定义好的函数;

函数的作用:在开发程序时,使用函数可以提高编写的效率以及代码的重用

<script>

    // 声明函数
    function sayHello() {
      console.log("Hello!")
      console.log("My name is Coderwhy!")
      console.log("how do you do!")
    }

    // 调用函数。在任何想要使用的时候, 进行调用
    sayHello()

</script>

2.3_函数的参数

函数的参数:增加函数通用性,针对 相同的数据处理逻辑

  • 在函数定义时,把参数当做 变量 使用,进行需要的数据处理

  • 在函数调用时,按照函数定义的参数顺序,把 在函数内部处理的数据,通过参数传递

形参和实参

  • 形参定义函数,小括号中的参数,是用来接收参数用的,在函数内部 作为变量使用

  • 实参调用函数,小括号中的参数,是用来把数据传递到 函数内部用的

 <script>

    function sum(num1, num2) {  //形参
      var result = num1 + num2
      console.log("result:", result)
    }

    sum(20, 30)  //实参
    sum(99, 200)  //实参

  </script>

2.4_函数的返回值

比如prompt函数:函数需要接受参数,并且会返回用户的输入,这个就是返回值

返回值:

  • 使用return关键字来返回结果;

  • 函数中执行return操作,当前函数会终止;

  • 如果函数中没有使用 return语句 ,有默认的返回值:undefined;

  • 如果函数使用 return语句,但是return后面没有任何值,函数的返回值也是:undefined

<script>
// 练习: 传入半径radius, 计算圆形的面积
    function getCircleArea(radius) {
      return Math.PI * radius * radius
    }
    var area1 = getCircleArea(10)
    var area2= getCircleArea(25)
    console.log("area1:", area1)
    console.log("area2:", area2)
</script>

arguments参数(JS高级)

  • 默认情况下,arguments对象是所有函数中都可用的局部变量(非箭头函数除外);

  • 该对象中存放着所有的调用者传入的参数,从0位置开始,依次存放;

  • arguments变量的类型是一个object类型( array-like ),不是一个数组,但是和数组的用法看起来很相似;

  • 如果调用者传入的参数多余函数接收的参数,可以通过arguments去获取所有的参数;

<script>
    // 1.arguments的认识
    function foo(name, age) {
      console.log("传入的参数", name, age)  // 传入的参数 shy 18

      // 在函数中都存在一个变量, 叫arguments。有点像数组,总共传入多少个参数,数组内就有多少个元素。
      console.log(arguments)  //Arguments(4) 
      // arguments是一个对象object
      console.log(typeof arguments)  //object
      // 对象内部包含了所有传入的参数
      // console.log(arguments[0])
      // console.log(arguments[1])
      // console.log(arguments[2])
      // console.log(arguments[3])

      // 对arguments来进行遍历
      for (var i = 0; i < arguments.length; i++) {
        console.log(arguments[i])
      }
      // shy 18 1.90 北京市
    }

    foo("shy", 18, 1.90, "北京市")


    // 2.arguments的案例
    function sum() {
      var total = 0
      for (var i = 0; i < arguments.length; i++) {
        var num = arguments[i]
        total += num
      }
      return total
    }

    console.log(sum(10, 20))  //50
    console.log(sum(10, 20, 30))  // 60
    console.log(sum(10, 20, 30, 40))  //100
  </script>

2.5_函数中调用函数

在开发中,函数内部是可以调用另外一个函数的

function Hi() {
      console.log("早上中午晚上好")
}

function Yes() {
     Hi()
     console.log("你也是")
}

函数中可以调用自己本身的函数, 但是函数调用自己必须有结束条件,否则会产生无限调用,造成报错。比如下面这种情况

function Hi() {
      console.log("早上中午晚上好")
      Hi()
}

Hi()

2.6_函数的递归

递归是一种重要的编程思想,同时必须注意,递归要有一个结束条件

    //递归实现  x的n次方 
    // 缺点: 性能是比较低(占用过多的栈内存)
    // 优点: 写出来的代码非常简洁
    function pow(x, n) {
      if(n === 1) return x 
      return x * pow(x, n-1)
    }

3_局部变量和外部变量

外部变量和局部变量的概念:

  • 定义在函数内部的变量,被称之为局部变量(Local Variables)。

  • 定义在函数外部的变量,被称之为外部变量(Outer Variables)。

全局变量

  • 在函数之外声明的变量(在script中声明的),称之为全局变量。

  • 全局变量在任何函数中都是可见的。

  • 通过var声明的全局变量会在window对象上添加一个属性(了解);

在函数中,访问变量的顺序: 优先访问自己函数中的变量,没有找到时,在外部中访问

<script>

    // 1.作用域的理解:message在哪一个范围内可以被使用, 称之为message的作用域(scope)
    // 全局变量: 全局作用域
    var message = "Hello World"
    if (true) {
      console.log(message)    //可以访问
    }
    function foo() {
      console.log("在foo中访问", message)   //可以访问
    }
    foo()

    // 2.ES5之前是没有块级作用域(var定义的变量是没有块级作用域)
    //一对花括号{}表示代码块
    {
      var count = 100
      console.log("在代码块中访问count:", count)   //可以访问
    }
    console.log("在代码块外面访问count:", count)  //可以访问
    // for循环的代码块也是没有自己的作用域
    for (var i = 0; i < 3; i++) {
      var foo = "foo"
    }
    console.log("for循环外面访问foo:", foo)    //可以访问
    console.log("for循环外面访问i:", i) // 3  可以访问

    // 3.ES5之前函数代码块是会形成自己的作用域
    // 意味着在函数内部定义的变量外面是访问不到的
    function test() {
      var bar = "bar"
    }

    test()
   
    //console.log("test函数外面访问bar:", bar)     //无法访问,报错

    // 函数有自己的作用域: 函数内部定义的变量只有函数内部能访问到
    function sayHello() {
      var nickname = "kobe"
      console.log("sayHello函数的内部:", nickname)   //可以访问 
      
      function hi() {
        console.log("hi function~")
        console.log("在hi函数中访问nickname:", nickname)  //可以访问 
      }
      hi()
    }
    sayHello()
    // console.log("sayHello外面访问nickname:", nickname)   //无法访问,报错

  </script>


4_函数表达式

在JavaScript中,函数不是一种神奇的语法结构,而是一种特殊的值, 定义函数的方式,称之为函数声明(Function Declaration);

另外一种写法是函数表达式(Function Expressions):注意,function 关键字后面没有函数名 ,函数表达式允许省略函数名。比如下面这个例子:

<script>  
  var test  = function (){
  	console.log("函数执行了")
  }
  
  test()    //函数执行了
      
</script>

函数用以上两种方法创建, 本质上,函数都是一个值(这个值的类型是一个对象object);

在JavaScript开发中,将函数作为头等公民


函数声明 VS 函数表达式

  • 语法不同

    • 函数声明:在主代码流中声明为单独的语句的函数。
    • 函数表达式:在一个表达式中或另一个语法结构中创建的函数。

  • JS创建函数的时机不同

    • 函数声明:被定义之前,它就可以被调用。这是内部算法的原故;当 JavaScript 准备 运行脚本时,首先会在脚本中寻找全局函数声明,并创建这些函数;
    • 函数表达式:在代码执行到达时被创建,并且仅从那一刻起可用。
<script>

    // 函数声明:先调用,再定义。不会报错
    test()
    function test() {
      console.log("test函数被执行了~")
    }

    // 函数表达式:先调用,再定义。肯定报错
    bar()
    var bar = function() {
      console.log("bar函数被执行了~")
    }

  </script>


5_JavaScript头等函数

头等函数(first-class function;第一级函数)是指在程序设计语言中,函数被当作头等公民。这意味着,函数可以作为别的函数的参数、函数的返回值,赋值给变量或存储在数据结构中

通常对作为头等公民的编程方式,称之为函数式编程。 JavaScript就是符合函数式编程的语言,这个也是JavaScript的一大特点;比如:函数可以在变量和变量之间相互进行赋值;

<script>

    // 函数作为头等公民
    // 1.函数可以被赋值给变量(函数表达式写法)
    var foo1 = function() {
      console.log("foo1函数被执行~")
    }
    // foo1()

    // 2.让函数在变量之间来回传递
    var foo2 = foo1
    foo2()


    // 3.函数可以另外一个函数的参数
    function bar(fn) {
       console.log("fn:", fn)
       fn()
    }
    bar(foo1)


    // 4.函数作为另外一个函数的返回值
     function sayHello() {
       function hi() {
         console.log("hi kobe")
       }
       return hi
    }

    var fn = sayHello()
    fn()


    // 5.将函数存储在另外一个数据结构中
    var obj = {
      name: "xixi",
      eating: function() {
        console.log("eating")
      }
    }
    obj.eating()
  
    function bar1() {
      console.log("bar1函数被执行~")
    }
    function bar2() {
      console.log("bar2函数被执行~")
    }
    function bar3() {
      console.log("bar3函数被执行~")
    }
    // 事件总线的封装
    var fns = [bar1, bar2, bar3]
	//函数作为参数时,只写函数名即可,不要加()
    // 函数式编程: 使用函数来作为头等公民使用函数, 这种编程方式(范式).
    // JavaScript支持函数式编程.

  </script>

回调函数(Callback Function)
函数可以作为一个值相互赋值,也可以传递给另外一个函数。

高阶函数必须至少满足两个条件之一:

  • 接受一个或多个函数作为输入参数;

  • 返回值输出一个函数;

匿名(anonymous)函数: 在传入一个函数时,没有指定这个函数的名词或者通过函数表达式指定函数对应的变量,那么这个函数称之为匿名函数。

<script>

    // 1.函数回调的概念理解
    function foo(fn) {
       // 通过fn去调用bar函数的过程, 称之为函数的回调
       fn()
    }
    function bar() {
       console.log("bar函数被执行了~")
    }
    foo(bar)


    // 2.函数回调的案例
    function request(url, callback) {
       console.log("根据URL向服务器发送网络请求")
       console.log("需要花费比较长的时间拿到对应的结果")
       var list = ["javascript", "javascript学习", "JavaScript高级编程"]
       callback(list)
    }

    function handleResult(res) {
       console.log("在handleResult中拿到结果:", res)
    }
   request("url", handleResult)


    // 3.函数回调的案例重构
    function request(url, callback) {
      console.log("根据URL向服务器发送网络请求")
      console.log("需要花费比较长的时间拿到对应的结果")
      var list = ["javascript", "javascript学习", "JavaScript高级编程"]
      callback(list)
    }

    // 传入的函数是没有名字, 匿名函数
    request("url", function(res) {
      console.log("在handleResult中拿到结果:", res)
    })

  </script>

6_立即执行函数

一个函数定义完后被立即执行

  • 第一:定义了一个匿名函数,这个函数有自己独立的作用域。

  • 第二:加后面的(),表示这个函数被执行了

 // 立即执行函数(常用的写法)
    (function() { 
      console.log("立即执行函数被调用~")
    })()

// 立即执行函数的参数和返回值
    var result = (function(name) {
      console.log("函数立刻被执行~", name)
      return "Hello World"
    })("why")
    console.log(result)

应用场景一: 防止全局变量的命名冲突。 在立即执行函数中定义的变量是有自己的作用域的

应用场景二:示例

<body>

  <button class="btn">按钮1</button>
  <button class="btn">按钮2</button>
  <button class="btn">按钮3</button>
  <button class="btn">按钮4</button>
  
  <script>

    // 1.获取一个按钮监听点击
    // 1.1 拿到html元素
    // var btnEl = document.querySelector(".btn")
    // console.log(btnEl)
    // 1.2 监听对应按钮的点击
    // btnEl.onclick = function() {
    //   console.log("点击了按钮1")
    // }

    // 2.获取所有的按钮监听点击
    // 没有使用立即执行函数
    //debugger
    // var btnEls = document.querySelectorAll(".btn")
    // for (var i = 0; i < btnEls.length; i++) {
    //   var btn = btnEls[i];
    //   btn.onclick = function() {
    //     console.log(`按钮${i+1}发生了点击`)
    //   }
    // }

    // 使用立即执行函数
    var btnEls = document.querySelectorAll(".btn")
    for (var i = 0; i < btnEls.length; i++) {
      var btn = btnEls[i];
      (function(m) {
        btn.onclick = function() {
          console.log(`按钮${m+1}发生了点击`)
        }
      })(i)
    }

    console.log(i)

  </script>

</body>


7_代码风格推荐

在这里插入图片描述



8_在Chrome进行JS调试debug


在JS代码里面写一句debugger,一旦运行到debugger就会自动卡在那里进入调试模式。如果第一次运行未进入调试模式,那么多刷新几次浏览器页面。

下图红框圈起来的图标作用:
1 继续执行脚本
2 跳过下一个函数
3 进入下一个函数内部
4 跳出当前函数调用
5 单步调试

在这里插入图片描述

推荐两篇文章

写得很好,介绍很全面


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值