练习向---循环分支--do while---for - 流程控制语句-arguments--预解析-函数的执行过程(牢记)

循环分支 - do while

+ 也是循环语法的一种
       +while 循环很像, 使用场景比较少

     while 语法
       while (条件) {
         代码
       }

     do while 语法
       do {
         代码
       } while (条件)while 的区别
       while 是先进行条件判断, 在决定是否执行代码
       do while 先执行一遍代码, 再开始进行条件判断, 决定时候继续执行代码

     区分:
       + 当初始条件在 结束条件以内的时候, while 和 dowhile 是一样的
       + 当初始条件在 结束条件以外的时候
         => while 循环一次都不会执行
         => do while 会执行一次

做一个 1 ~ 10 的循环

var n = 1
do {
     console.log(n)
     n++
 } while (n <= 10)

循环分支 - for 循环

语法:
     for (定义初始变量; 条件判断; 改变初始变量) {
       重复执行的代码
     }
     原始形态
     定义初始变量
     for (; 条件判断; ) {
       重复执行的代码
       改变初始变量
     }

1 ~ 10 的数字

var n = 1
 for (; n <= 10;) {
  console.log(n)
  n++
}

流程控制语句

1. break
  + 使用在循环内的关键字
  + 当循环内遇到 break 的时候, 会直接结束当前循环

2. continue
  + 使用在循环内的关键字
  + 当循环内遇到 continue 的时候, 会结束循环的本次, 直接去到修改变量位置

3. 标记语法
  + 可以给 循环打上标记
  +break 或者 continue 的时候, 直接跳出到标记位置
  + 目的: 默认 breakcontinue 是在当前循环内生效
gx:
for (var i = 1; i <= 5; i++) {
  console.log('------------------------------')
  console.log(`我拿起了第 ${ i } 个包子`)
  for (var j = 1; j <= 3; j++) {
    console.log(`我咬下了第 ${ j }`)
    if (i === 3 && j === 2) {
      console.log('看到了 半条虫子 ')
      // 不吃了
      // 当你结束的时候, 我是想结束 gx 这个被标记的循环
      break gx
    }
  }
  console.log(`${ i } 个包子吃完了`)
  console.log('------------------------------')
}

认识函数

1. 什么是函数
	  => 一个 javascript 内的复杂数据类型
	  => 私人: 一个承载一段代码的 "盒子"

2. 函数的两个阶段
  2-1. 函数的定义阶段
	    => 声明式函数: function 函数名() {}
	    => 函数表达式: var 函数名 = function () {}
  2-2. 函数的调用阶段
	    => 函数名()
	    => 注意: 声明式函数可以先调用可以后调用, 函数表达式只能后调用

3. 函数的参数
  3-1. 形参
	    => 书写在函数定义阶段的小括号内
	    => 就是一个只能在函数内使用的变量
	    => 可以书写多个, 多个之间使用 逗号(,) 分隔
	    => 值由函数调用时的实参决定
  3-2. 实参
	    => 书写在函数调用阶段的小括号内
	    => 就是按照顺序依次给函数的形参赋值
	    => 可以书写多个, 多个之间使用 逗号(,) 分隔
  3-3. arguments
	    => 函数内天生自带的变量, 就是函数所有实参的集合
	    => length 属性
	      -> 语法: arguments.length
	      -> 得到: 该 arguments 的长度, 也就是有多少个实参
	    => 索引 属性
	      -> 索引:0 开始, 依次 +1
	      -> 通过索引可以访问到 arguments 内某一个数据
	      -> 语法: arguments[索引]
	   	 => 遍历
	      -> 利用循环对 arguments 进行遍历
	      -> 示例:
		        for (var i = 0; i < arguments.length; i++) {
		          // i 分别表示 arguments 内每一个数据的索引
		          // arguments[i] 分别表示每一个数据
		        }

4. 函数的 return
  4-1. 函数的返回值
        =>在函数内可以使用一个叫做 return 的关键字
	    =>给该函数创建一个返回值(结果),写在 return 后面的内容就是该函数执行完毕以后得到的结果
  4-2. 打断函数
	    => 当函数内遇到 return 关键字的时候
	    => 后续代码不在执行了
//1. 声明式函数
function fn() {
  console.log('我是被装进盒子的一段代码')
}
console.log(fn)

//2. 赋值式函数
var fn2 = function () {
  console.log('我是第二段代码, 我也被装进了盒子')
}
console.log(fn2)

//函数调用
fn()
fn2()
fn()
fn2()

函数的参数

+ 目的: 为了在你封装函数的时候, 增加更多的定制性

函数的参数分成两种
	 + 形参
	   => 书写在函数定义阶段的 小括号 
	   => 就是一个只能在函数内使用的变量
	   => 可以书写多个, 多个之间使用逗号(,) 分隔
	   => 形参的值, 由函数调用时的实参决定
 + 实参
	   => 书写在函数调用阶段的 小括号 
	   => 就是按照顺序依次给函数的形参赋值
	   => 可以书写多个, 多个之间使用逗号(,) 分隔

arguments

arguments
  + 是什么?
	    => 是函数内天生自带的变量, 可以直接使用
	    => 是一个集合("盒子"), 承载的是该函数被调用时的全部实参

arguments 的基本操作
  1. length 属性
	    + 语法: arguments.length
	    + 得到: 是一个数值类型, 表示该 arguments 的长度, 也就是 arguments 内有多少个数据
  2. 索引 属性
    + 索引:
	      => arguments 内的数据排列是有顺序的
	      =>0 开始, 依次 +1
	      => 我们管这个数据排列的 "序号", 叫做 索引或者下标
    + 索引和 length 的关系
	      	=> 最后一位的索引一定是 length-1
    + 利用索引可以访问 arguments 内的数据
	      => 语法: arguments[索引]
	   	-> 如果 arguments 内有该索引位置, 那么就是该索引位置的数据
        -> 如果 arguments 内没有该索引位置, 那么就是 undefined
  3. 遍历 arguments
    + 意义: 依次访问数据集合内的每一个数据
    + 规律: arguments 内每一个数据的索引是一组有规律的数字
           循环可以给我们提供一组有规律的数字
           利用 循环, 来遍历 arguments

预解析

+ 在代码执行之前, 对代码进行通读并解释
+ 在预解析的过程中
	  => 只会解析全局代码, 函数内的代码不会进行预解析
	  => 会在函数执行的时候, 才进行预解析

解释的内容
1. var 关键字声明的变量
	  => 告诉浏览器, 我定义了一个 xxx 变量, 但是还没有赋值
	  => 赋值式函数按照 var 的规则来执行

2. 声明式函数
	  => 告诉浏览器, 我定义了一个 xxx 变量(函数名), 并且赋值为一个 函数

var 的预解析

console.log(num)
var num = 100
console.log(num)

代码执行过程

1. console.log(num)
2. var num = 100
3. console.log(num)

打开浏览器

预解析
  1. 不需要预解析
  2. 需要预解析
	    => var num
	    => 告诉浏览器我定义了一个叫做 num 的变量
  3. 不需要预解析

执行代码
  1. console.log(num)
	    => 预解析已经声明了 num 变量, 目前内存中是有 num 变量的
	    => undefined
  2. num = 100
	    => 给 num 变量赋值为 100
  3. console.log(num)
	    => 100

声明式函数预解析

fn()
function fn() { console.log('fn') }
fn()

代码执行过程

1. fn()
2. function fn() { console.log('fn') }
3. fn()

打开浏览器
预解析
	  1. 不需要预解析
	  2. 需要预解析
		    => 在浏览器声明了一个变量叫做 fn, 并且赋值为一个函数
	  3. 不需要预解析

代码执行
  1. fn()
	    => 因为在预解析阶段, 已经把 fn 定义为一个函数了
	    => 正常执行
  2. 不需要
  3. fn()
	    => 原因同上

赋值式函数预解析

fn()
var fn = function () { console.log('你好 世界') }
fn()

代码执行过程

1. fn()
2. var fn = function () { console.log('你好 世界') }
3. fn()

打开浏览器
预解析
	  1. 不需要预解析
	  2. 需要
		    => var fn
		    => 告诉浏览器我定义了一个叫做 fn 的变量, 暂时没有赋值
	  3. 不需要预解析

代码执行
  1. fn()
	    => 此时 fn 变量存在, 但是值是一个 undefined
	    => fn()undefined 当做一个函数来调用
	    => 报错: fn is not a function

函数名和变量名重名

说明: 该文件内
	=> 函数指函数名
	=> 变量指的是保存非函数的变量
	
函数名和变量名重名
	=> 当一个 变量 和 函数名 重名的时候
	=>**预解析阶段** , 以函数为准
fn()
function fn() { console.log('我是一个函数') }
fn()
var fn = 100
fn()

代码执行过程

1. fn()
2. function fn() { console.log('我是一个函数') }
3. fn()
4. var fn = 100
5. fn()

打开浏览器
预解析
	  1. 不需要
	  2. 需要
		    => 告诉浏览器, 我定义了一个叫做 fn 的变量, 并且赋值为一个函数
	  3. 不需要
	  4. 需要
		    => var fn
		    => 告诉浏览器, 我定义了一个叫做 fn 的变量
	  5. 不需要
	  + 当预解析结束的时候, 浏览器内只有一个 fn 变量, 并且被赋值为了一个 函数

执行代码
	  1. fn()
		    => 因为预解析阶段已经把 fn 赋值为一个函数了
		    => 正常调用
	  2. 不用管
	  3. fn()
		    => 原因同上
	  4. fn = 100
		    => 给 fn 变量赋值为 100
		    => 因为 fn 本身保存的是 一个函数
		    => 100函数覆盖了
		    => 从此以后 fn 就是 100 这个数字了
	  5. fn()
		    => 因为 第 4 行代码的执行, 把 fn 赋值为 100 
		    =>100 当做一个函数来调用
		    => fn is not a function

函数的执行过程(牢记)

内存的存储过程
	+ 当你定义一个变量(变量和函数)的时候
	+ 会在内存中开辟一段区域来存储内容
	+ 浏览器把存储部分分成了两个区域
1. 栈内存
2. 堆内存
	+ 在存储的过程中
		=> 基本数据类型, 直接把值保存在栈内存里面
		=> 复杂数据类型
			-> 数据存储在堆里面
			-> 把地址存储在栈内的变量里面


函数的两个阶段(熟读并背诵全文)
函数定义阶段
	1. 在堆内存中开辟一段空间
	2. 把函数体内的代码一模一样的当做一个字符串存储在空间中(不执行代码, 不解析变量)
	3. 把空间地址赋值给栈内存中的变量名

函数调用阶段
	1. 按照变量名存储的地址找到一个对应的堆内存中的空间
		1-1. 判断变量名是否存在, 如果不存在: xxx is not defined
		1-2. 按照变量名存储的地址查找, 如果不是一个函数存储空间: xxx is not a function
	2. 在 调用栈 中开辟一段新的代码执行空间
	3. 在开辟的代码执行空间中进行 形参赋值
	4. 在开辟的代码执行空间中进行 预解析
	5. 把存储空间内的代码一模一样的复制一份放在执行空间内执行一遍(此时才开始解析变量)
	6. 当代码执行完毕以后, 该执行空间销毁

代码解读

var num = 100
    function fn() {
      // 如果我在定义阶段不解析变量, 那么我存储起来的应该是 'console.log(num)'
      // 如果我在定义阶段就解析变量, 那么我存储起来的应该是 'console.log(100)'
      console.log(num)
    }
    num = 200
    如果 定义阶段没有解析变量, 那么 num = 200 会影响函数的执行, 打印出来就是 200
    如果 定义阶段解析了变量, 那么 num = 200 不影响函数的执行, 打印出来依旧是 100
    fn()

分析:

假设: 先 形参赋值 后 预解析
	  1. 给 a 赋值为 100
	  2. 在预解析阶段给 a 赋值为 函数, 此时会覆盖 100
	  + 当函数体内的代码在执行的时候, a 打印出来就是 函数体

结社: 先 预解析 后 形参赋值
	  1. 在预解析阶段给 a 赋值为 函数
	  2. 给 a 赋值为 100, 就会覆盖本身的 函数
	  + 当函数体内的代码在执行的时候, a 打印出来的就是 100
*/
function fn(a) {

// 打印 a 变量
console.log(a)
function a() {}
}

// 本次调用的时候, 100 赋值给了形参 a
fn(100)

作用域

一个变量(变量和函数)的生效范围

作用域的分类
1. 全局作用域
	=> 一个 html 页面打开, 就是一个全局作用域
	=> window
2. 私有作用域(函数作用域)
	=> 概念: **只有函数生成私有作用域**

提供了三个机制
1. 变量定义机制
	=> 定义在哪一个作用域下的变量就是哪一个作用域的私有变量
	=> 只能在该作用域以及后代作用域使用
2. 变量访问机制
	=> 当你需要访问某一个变量的值的时候
	=> 首先在自己作用域内查找, 如果有直接使用, 停止查找
	=> 如果没有, 去到父级作用域查找, 如果有直接使用, 停止查找
	=> 如果还没有, 在去到父级作用域查找
	=> 以此类推, 直到全局作用域(window) 都没有, 报错: xxx is not defined
3. 变量赋值机制
	=> 当你需要给一个变量赋值的时候
	=> 首先在自己作用域内查找, 如果有直接赋值, 停止查找
	=> 如果没有, 去到父级作用域查找, 如果有直接赋值, 停止查找
	=> 如果还没有, 就在去到父级作用域查找
	=> 以此类推, 直到全局作用域(window) 都没有
	=> 把该变量定义为 **全局变量** 在进行赋值

分清变量的三种情况
1. 变量定义
	=> 必须要有定义变量的关键字
		-> var / function
	=> 函数的形参
2. 变量访问
	=> 当你需要用到某一个变量的值
3. 变量赋值
	=> 当你需要给一个变量进行赋值操作
	=> 特点: 有赋值符号 或者 实参和形参的交互

function a() {
  // 此处位置就是 a 私有作用域, 父级作用域是 window
  // 子级作用域是 b
	  function b() {
	    // 此处位置就是 b 私有作用域
	    //   父级作用域是 a
	    //   子级作用域是 c
	    function c() {
	      // 此处位置就是 c 私有作用域
	      // 父级作用域 b
	    }
	  }
}
function d() {
  // 此处位置就是 d 私有作用域
  // 父级作用域是 window
}

封装函数

  • 计算两个数字的最大公约数
function fun(a,b){
    if(a%b == 0) return b;
    else return fun(b,a%b);    	
}
console.log(fun(12,8));

var gcd = function(a, b){
            return b ? gcd(b, a % b) : a;
        }
-------------解析--------------
var gcd = function(a, b){
  return b ? gcd(b, a % b) : a;//把a%b==0这个条件直接简化为递归后判断最新的b !== 0
      // 8       8    4
      // 4       4    0
      // 0                   4
}
console.log(gcd(12,8));
-------------转化为箭头函数--------------
var a = 12,b = 8;
fun_2 = (a,b)=> b ? fun_2(b, a % b) : a
console.log('最小公约数',a*b/fun_2(a,b));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值