作者小头像 Lv.1
18 成长值

个人介绍

这个人很懒,什么都没有留下

感兴趣或擅长的领域

暂无数据
个人勋章
  • 活跃之星
成长雷达
0
18
0
0
0

个人资料

个人介绍

这个人很懒,什么都没有留下

感兴趣或擅长的领域

暂无数据

达成规则

发布时间 2020/07/13 10:25:31 最后回复 blateyang 2020/08/20 23:20:02 版块 社区活动
32616 468 0
他的回复:
华为云ID:hw09068607 ## 1 数据类型 ### 1.1 初识JS 1. 什么是JS? JS是用于网页开发实现网页动态交互的高级脚本语言,原名Livescript(后面为了蹭Java热度,改名为JavaScript),由Netscape公司发明,后交由Mozilla基金会(MDN)维护。 JS的标准是ECMAScript,目前普遍使用的版本是ECMAScript5.1(ES5),最新版本是ES6(2015年发布) 2. JS的执行原理 由浏览器的JS引擎逐行读取JS代码解释执行,读取一行执行一行 3. JS的三大组成部分 - ECMAScript - 文档对象模型DOM - 浏览器对象模型BOM 4. JS的输入输出语句 - 弹窗式输出:`alert('hello')` - 控制台打印式:`console.log('hello')` - 弹窗式输入:`prompt('提示文本')` ### 1.2 变量 1. 变量的主要作用 用于存储数据 2. 变量的初始化 ```javascript var v1 = 1; let v2 = 'a'; ``` var和let的区别: let是后出现的,相比var使用更规范(如var可以重复声明变量但let不行),条件允许建议使用let 3. 变量的命名规范 和C/C++/Java相比多了一个$,即由数字、字母、下划线和$组成且开头不能是数字 4. 变量在内存中如何存储的? 声明变量后会在内存中开辟一段空间并将变量名指向该内存空间 ### 1.3 数据类型导读 1. 5种简单的数据类型 - number数字型 - string字符串型 - boolean布尔型 - undefined - null 2. 如何获取变量类型 使用`typeof 变量名` 3. 字符串转换为数值型的方法 - parseInt()和parseFloat() - 使用Number()强制类型转换 - 利用算术运算- * /进行隐式转换(JS引擎根据上下文推断变量的数据类型,不能直接运算是会尝试进行自动转换) `console.log(‘12’-0)` 4. 转换为字符串型的方法 - 使用+和空字符串拼接 `console.log(1+"")` - toString()方法 ## 2 运算符 ### 2.1 常用运算符 1. 算术运算符 +,-,*,/ 2. 关系运算符 >,,>=,= 3. 相等运算符 ==,!=,===,!==(后两个不仅值要相等,类型也要相等) 3. 逻辑运算符 &&,||,! 5. 赋值运算符 **补充** 逻辑中断(短路)运算符(使用非布尔值参与逻辑运算) 短路运算的原理:当有多个表达式(值)参与运算时,如果左边的表达式(值)可以确定,就不再继续运算右边的表达式的值 1. 逻辑中断逻辑与: `表达式1&&表达式2` - 如果第一个表达式的值为真,返回表达式2 - 如果第一个表达式的值为假,返回表达式1 2. 逻辑中断逻辑或: `表达式1||表达式2` 规则与逻辑与相反 注意:表达式的值为空的或否定的为假,如`0,null,false,NaN,undefined` ### 2.2 前置递增和后置递增的区别 ### 2.3 运算符优先级 大体逻辑: - 单目(!,++,--,etc)>双目 - 算术>关系>逻辑>赋值>逗号 ## 3 流程控制 ### 3.1 if分支语句 ``` if(判断条件) { }else if(){ }else{ } ``` ### 3.2 switch分支 ``` switch(分支变量) { case 分支变量值1: ... break; case 分支变量值2: ... break; default: ... break; } ``` **switch和ifelseif区别:** - switch通常处理case为比较确定值的情况;ifelseif语句适合范围判断 - switch语句条件判断后直接执行相应语句,执行效率更高一些 - switch更适合分支多的情况,ifelseif更适合分支少的情况 ### 3.3 循环 1. 循环的目的 - 重复执行某些操作 2. for循环 ``` for(初值条件;循环终止条件;循环递增){ 循环体; } ``` 3. while循环和do while循环 - while循环:先判断后执行 - do while循环:先执行后判断 4. break和continue区别 - break:终止跳出循环 - continue:结束当前循环进入下次循环 ## 4 数组 ### 4.1 为什么要有数组 可以用来存储一系列不同的元素,类似python中的list ### 4.2 如何创建数组 ``` var arr = []; // 空数组 arr = [1, 'a']; ``` ### 4.3 如何获取数组中的元素 利用下标访问 ### 4.4 如何对数组遍历 ```javascript for(let k in arr) { console.log("key:"+ k + ",value:" + arr[k]); } ``` ### 4.5 数组转字符串 - `arr.join(分隔符)` - `arr.toString()` ### 4.5 给数组新增元素 - 尾部新增:`arr.push()` - 头部新增:`arr.unshift()` ### 4.6 删除数组元素 - 尾部删除:`arr.pop()` - 头部删除:`arr.shift()` ### 4.7 冒泡排序 ```javascript let arr = [3, 4, 1, 2]; for(let i=0; i arr[j+1]) { let tmp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tmp; } } } console.log(arr) ```
发布时间 2020/07/13 10:25:31 最后回复 blateyang 2020/08/20 23:20:02 版块 社区活动
32616 468 0
发布时间 2020/07/13 10:25:31 最后回复 blateyang 2020/08/20 23:20:02 版块 社区活动
32616 468 0
他的回复:
华为云ID: hw09068607 ## 前端经典面试题解析 面试的本质: 面试官通过问面试题摸清面试者的技术水平 1 对面试题的一些误解 1.1 企图通过刷海量的题来通过面试(题海战术耗精力,且靠刷题刷出来的能力不长久) 1.2 认为自己经验丰富,完全不需要准备(人总有遗忘的知识点) 2 面试题的特点 - 通用性 - 主观性 - 局限性 Tips: **牢固掌握基础知识,熟悉常见面试题** 基础没打好,单纯刷题效果不大 3 前端经典面试题 以前端三件套:HTML,CSS,JS为例 特点:**由点到面**(由汽车噪音大的现象问可能产生的原因及相应解决办法) e.g.1 H5标签语义化如何理解? 开放性问题:尽力发挥,充分展示自己知道的知识 - 结构更清晰 - 便于搜索引擎识别优化 e.g.2 如何能让一个元素垂直居中? 考察CSS,至少能够答出2个以上答案,最好能发散扩展,如水平居中,水平+垂直居中 ```html``` 华为云专家张宇给出的几种常见水平+垂直居中方法 法1:外flex布局+内margin:auto ```css .outDiv { width: 200px; height: 200px; border: black solid 2px; display: flex; } .inDiv { background: red; width: 50%; height: 50%; margin: auto; } ``` 法2: 内absolute定位+transform: translate(-50%, -50%) ```css .outDiv { width: 200px; height: 200px; border: black solid 2px; position: relative; } .inDiv { background: red; width: 50%; height: 50%; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } ``` 法3: 外table-ceil布局结合vertical-align和text-align属性+内display:inline-block ```css .outDiv { width: 200px; height: 200px; border: black solid 2px; display: table-cell; text-align: center; vertical-align: middle; } .inDiv { background: red; width: 50%; height: 50%; display: inline-block; } ``` 法4:内position: absolute + top,right,bottom,left均为0 + margin:auto ```css .outDiv { width: 200px; height: 200px; border: black solid 2px; position: relative; } .inDiv { position: absolute; background: red; width: 50%; height: 50%; top: 0; right: 0; bottom: 0; left: 0; margin: auto; } ``` e.g.3 如何适配不同尺寸手机屏幕实现响应式布局? 考察CSS的相对单位,如vw,vh,rem(相对根元素html的大小),百分比 e.g.4 变量和函数提升 ```javascript fun(); function fun() { console.log("fun"); } var f = function b() { console.log("f"); } f(); b(); // 运行结果 fun f f ``` e.g.5 闭包{}{} ```javascript for(var i=0; i5; i++) { setTimeOut(function() { console.log(i); }, i*1000); } // 运行结果是 5 5 5 5 for(var j=1; j5; j++) { (function(k) { setTimeout(function() { console.log(k); }, k*1000); })(j); // 将j作为实参传递给内部函数并立即执行 } // 运行结果 (隔1s)1 (隔2s)2 (隔3s)3 (隔4s)4 ``` e.g.6 this和fun.call() ```javascript function foo(num) { console.log("foo"+num); this.count++; } foo.count = 0; for(var m=0; m10; m++) { if(m > 5) { foo.call(foo, m); } } console.log(foo.count); // 运行结果 foo6 foo7 foo8 foo9 4 ```
发布时间 2020/07/13 10:25:31 最后回复 blateyang 2020/08/20 23:20:02 版块 社区活动
32616 468 0
他的回复:
华为云ID:09068607 ## 1 初识AJAX AJAX是Asynchronus JavaScript And XML的简称,它可以在不刷新整个网页的情况下异步地和服务器进行数据通信来进行局部更新 ### 1.1 AJAX技术的优势 - 大幅提升用户体验(表单异步验证的例子) - 能够减轻服务器端的压力(异步分部分加载服务器数据) - 异步加载(异步与服务器通信) - 局部更新(无刷新更新数据) - 前端和后端负载均衡 ### 1.2 网络通信 1. OSI七层模型(自顶向下) - 应用层:为应用程序提供服务 - 表示层:进行编码转换、数据加密等 - 会话层:建立、管理和维护会话 - 传输层:建立、管理和维护端到端的连接>TCP&UDP- 网络层:IP选址和路由选择>路由器 - 数据链路层:提供介质访问和链路管理>交换机 - 物理层:传输二进制信号 2. TCP/IP协议 传输控制协议/网络协议 3. HTTP协议 特点: - 无状态协议 - 不会建立持久连接 HTTP通信机制:基于请求-响应模式 ## 2 Node.js服务 Node.js是基于Chrome V8引擎的javascript运行时 ### 2.1 安装和验证 官网下载安装包直接安装,可通过node -v和npm -v验证是否安装成功 npm是node的包管理器,用npm安装的依赖包通常放在国外的网站,可利用淘宝的cnpm代替npm进行安装 安装cnpm的命令为 `npm install -g cnpm --registry=https://registry.npm.taobao.org` ### 2.2 koa2框架 koa是Node.js的下一代Web框架,借助大量中间件(类似插件),koa代码量非常少,分2个版本koa v1和koa v2 ### 2.3 搭建web服务器 - 使用`cnpm install koa-generator -g`可以安装koa-generator脚手架,方便生成项目 - 使用koa2命令创建项目 `koa2 项目名` - 使用cnpm install安装依赖包 - 使用npm start运行项目 ## 3 揭秘AJAX ### 3.1 XHR(XMLHttpReaquest) 方法: - open() 初始化 - send() 发送 - setRequestHeader Content-type 属性: - onreadystatechange - readyState - status - responseText ### 3.2 XHR四步走 1. 创建XHR 2. 使用open方法,初始化请求参数 ```js open(method, url, async); setRequestHeader("Content-type", "application/x-www-form-urlencoded"); ``` 3. 使用send方法,发送请求 `send(param)` 4. 使用onreadystatechange属性,接收返回数据 - readyState: 4(代表XHR对象已处于最后的就绪状态) - status: 200(代表请求已成功的回来了) ```js var xhr = null; // 1. 创建xhr对象 if(window.XMLHttpRequest) { xhr = new XMLHttpRequest(); }else if(window.ActiveXObject) { xhr = new ActiveXObject(); // 兼容IE8以下的低版本浏览器 } // 2. 初始化xhr xhr.open("get", "/ajax", true); xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); // 3. 发送请求 xhr.send(); // 4. 获取响应 xhr.onreadystatechange = function() { if(xhr.readyState == 4) { if(xhr.statue == 200) { console.log(xhr.responseText); } } } ``` ### 3.3 跨域请求 1. 同源策略 - 浏览器的安全策略 - 规则:依据**协议名+主机名/IP+端口号**判断是否同源 2. 跨域请求 - 跨域的方法:JSONP, Proxy, [iframe(要结合window.name)](https://www.cnblogs.com/happy-8090/p/11570998.html), CORS - 天然可跨域的标签:script(image,link) 常用的是通过JSONP跨域,其原理是利用天然可跨域的script的src属性拿到不同源的数据
发布时间 2020/07/13 10:25:31 最后回复 blateyang 2020/08/20 23:20:02 版块 社区活动
32616 468 0
他的回复:
华为云ID:09068607 ## 1 JS对象基础 ### 1.1 何为对象以及为何需要对象? - 对象是一个**具体的事物**,由属性和方法构成。女朋友不是对象,志玲姐姐才是对象(可惜志玲姐姐已经有对象了T_T) ![图片.png](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/attachment/forum/202008/02/120110wvdl3x0qqplwfnv0.png) - 使用对象来表示事物结构更清晰,其本质是一组无序的相关属性和对象集合 ### 1.2 创建对象的三种方法 #### 1.2.1 利用对象字面量创建对象 ```js // 创建对象 var dateObj = { name: "ygj", age: 26, sayHi: function() { alert("hi") } } // 使用对象 // 1. 对象.属性 dateObj.name; // 2. 对象["属性"] dateObj["name"] // 3. 调用方法 dateObj.sayHi(); ``` **补充**:变量、属性、函数、方法的比较 变量:单独声明赋值,单独存在 属性:对象中的变量,不需要声明,用来描述对象的特征,需要使用`对象.属性`或`对象["属性"]`访问 函数:单独存在,通过`函数名()`调用 方法:对象中的函数,用来描述对象的行为,使用`对象.方法()`调用 #### 1.2.2 利用new Object()创建对象 ```js var dateObj = new Object(); dateObj.name = 'ygj'; dateObj.age = 28; dateObj.sayHi = function() {alert("hi");}; ``` #### 1.2.3 利用构造函数创建对象 1. 为何需要这种创建方式? 前两种创建方式一次只能创建一个对象,而有时创建对象的方式相似,为避免重复书写,借用函数的思路编写专门创建对象的函数。 构造函数类似java/c++里面的类,泛指某一大类 2. 构造函数的语法 ```js // 声明 function 构造函数名(args...) { // 构造函数名需首字母大写 this.属性 = 值; // 属性和方法前必须加this,代表当前对象 this.方法 = function() {} } // 构造函数不需要return就可以返回结果 // 使用 new 构造函数名(); // 必须用new来调用构造函数,返回的是创建的对象 ``` 3. new的执行过程 (1)new 构造函数可以在内存中创建一个空的对象 (2) this就会指向刚创建的空对象 (3)执行构造函数里面的代码,为空的对象添加属性和方法 (4) 返回新对象(所以构造函数里面不需要return) ### 1.3 使用for...in遍历对象属性 ```js for (var key in dateObj) { console.log(key); // key代表属性名 console.log(dateObj[key]); // dateObj[key]代表属性值 } ``` ## 2 内置对象 ### 2.1 JS对象类型 - 自定义对象 - 内置对象 - 浏览器对象 ### 2.2 查文档方法 最常用的是[MDN](https://developer.mozilla.org/zh-CN/)/W3C - 看函数功能 - 看参数含义和类型 - 看返回值 - 通过demo进行测试 ### 2.3 内置对象 #### 2.3.1 数学对象Math的常用属性和方法 - Math.PI:圆周率 - Math.max() - Math.min() - Math.abs():求绝对值 - 三个取整方法: - Math.floor() 向下取整 - Math.ceil() 向上取整 - Math.round() 四舍五入 - Math.random():取随机数 #### 2.3.2 日期对象Date的常用属性和方法 Date对象必须用构造函数来创建,即`new Date()` 参数说明: ```js new Date(); // 不带参,返回当前系统时间 new Date(2020, 8, 2); // 数字型,8代表9月,返回的是“2020-09-02” new Date("2020-8-2 7:4:0"); // 字符串型 ``` 1. 格式化日期 - dateObj.getFullYear() - dateObj.getMonth() - dateObj.getDate() - dateObj.getDay(): 获取周几(周日0-周六6) - dateObj.getHours() - dateObj.getMinutes() - dateObj.getSeconds() 2. 获得自1970-1-1的总毫秒数(时间戳) ```js var date = new Date(); // 1. 通过valueOf()或getTime() date.valueOf(); date.getTime(); // 2. 简单写法(最常用) +new Date(); // 3. H5新增的 Date.now() ``` #### 2.3.3 数组对象Array的常用属性和方法 1. 创建数组对象的两种方法 - 利用数组字面量:`var arr = [1,2,3]` - 利用构造函数: `var arr = new Array()` ```js new Array(length); // 1个参数代表元素个数 new Array(2,3); // 2个以上代表数组元素 ``` 2. 检测是否为数组的两种方法 - instanceof 运算符(返回bool值): `obj instanceof Array` - Array.isArray() 方法: `Array.isArray([1, 2, 3])` 3. 增加元素的方法 - push(args):在数组尾部添加1个或多个元素,返回新数组的长度 - unshift(args):在数组开头添加1个或多个元素,返回新数组的长度 4. 删除元素的方法 - pop(): 删除数组最后的元素,返回被删除的元素 - shift(): 删除数组第一个元素,返回被删除的元素 5. 数组排序方法 - reverse():反转数组 - sort(comparefunc):排序数组 ```js arr.sort(function (a, b) { return a-b; // 升序排序 // return b-a; // 降序排序 }) ``` 6. 数组索引方法 - indexOf(item, [startFrom]): 返回数组元素的第一个满足条件的索引号,没有返回-1,可选参数startFrom可指定起始位置 - lastIndexOf(): 返回数组元素最后一个满足条件的索引号,没有返回-1 【应用案例】:数组去重 核心思想:遍历旧数组,拿每一个元素去新数组中查,如果没有则加入新数组 ```js var arr = ['a', 'b', 'a', 'c']; var newArr = [] for (var i=0; i{ newArr.push(arr[i]); } } ``` 7. 数组转字符串 - toString()方法:`arr.toString()`, 默认用','连接字符串 - join(分隔符)方法:可以指定分隔符 8. 基本包装类型 将简单数据类型包装成复杂数据类型,这样简单数据类型就有属性和方法了,JS对String,Number和Boolean都有包装 ```js var str = "blate"; console.log(str.length); // 会输出5,普通字符串本来是没有length属性的,能够输出是因为JS做了包装 // 等价于如下过程 var tmp = new String("blate"); // 生成临时变量进行包装 str = tmp; // 赋值 tmp = null; // 销毁临时变量 ``` #### 2.3.4 字符串对象 1. 字符串的不可变性:对字符串的任何修改操作都会返回新的字符串,不适合做大量拼接,很消耗内存 2. 根据字符返回位置,同数组的indexOf()和lastIndexOf()方法 3. 根据位置返回字符: - charAt(idx) - charCodeAt(idx)返回索引位置字符的ASCII码,方便检测用户按键 - str[idx] H5新增(IE8+支持) 【应用案例】找出出现次数最多的字符 核心思路:利用对象建立字符和出现次数的哈希映射,如果对象obj存在字符属性ch,obj[ch]能够通过if判断,最后遍历对象属性找到出现最多的字符 ```js var str = "blateyang"; var obj = {}; for(var i=0; i }else{ obj[ch]++; } } var max = 0; var maxCh = ""; for(k in obj){ if(obj[k] > max){ max = obj[k]; maxCh = k; } } console.log(maxCh + ":" + max); ``` 4. 字符串的拼接和截取 - concat(str1, str2...):拼接字符串=>str1 + str2 - substr(startFrom, num): 截取从startFrom开始的num个字符串 5. 字符串的替换和转数组 - str.replace(srcChar, dstChar):用dstChar替换str中的srcChar字符,只替换一次 - str.split(delimit):将str按分隔符delimit转成数组 6. 大小写转换 - toUpperCase():转大写 - toLowerCase():转小写 ### 3 简单数据类型和复杂数据类型 #### 3.1 数据类型内存分配 - 简单数据类型(又称值类型):在存储时变量存的是值本身,有5种:string, number, boolean, undefined, null(空对象) - 复杂数据类型(也称引用类型):在存储时变量存的是地址(引用),该地址指向存放在堆中的实际复杂数据 #### 3.2 简单数据类型的参数传递 采用值传递的方式 ```js function testArgs(argu) { argu++; return argu; } argu = 1; console.log(testArgs(argu)); // 2 console.log(argu); // 1 ``` #### 3.3 复杂数据类型的参数传递 复杂数据类型按照地址传递 ```js function Person(name) { this.name = name; } function f1(x){ x.name = "Mike"; console.log(x.name); } var p = new Person("Blate"); console.log(p.name); // "Blate" f1(p); // p将其保存的地址传给了形参x console.log(p.name); // "Mike" ``` ![复杂数据类型内存模型.PNG](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/attachment/forum/202008/02/1159458voawbf2qu9igbkr.png)
发布时间 2020/07/13 10:25:31 最后回复 blateyang 2020/08/20 23:20:02 版块 社区活动
32616 468 0
他的回复:
华为云ID:09068607 ## 1 函数 ### 1.1 JS参数传递形式 简单数据类型按照值传递 ``` function testArgs(argu) { argu++; return argu; } argu = 1; console.log(testArgs(argu)); // 2 console.log(argu); // 1 ``` 复杂数据类型按照地址传递 ``` function Person(name) { this.name = name; } function f1(x){ x.name = "Mike"; console.log(x.name); } var p = new Person("Blate"); console.log(p.name); // "Blate" f1(p); // p将其保存的地址传给了形参x console.log(p.name); // "Mike" ``` ### 1.2 函数形参与实参个数不匹配问题 - 实参个数多于形参,只取到形参个数 - 实参个数少于形参,没有接受到实参的形参(可以看作是不用声明的变量)是undefined e.g. ``` function getSum(num1, num2) { return num1 + num2; } getSum(1); // 1 + undefined -> NaN ``` ### 1.3 函数返回值 - 函数有return,返回return后面的值 - 函数没有return,返回的是undefined ### 1.4 arguments的使用 arguments是每个函数内置的一个对象,里面按照伪数组的形式存储了所有传递过来的实参 ### 1.5 函数的两种声明方式 1. 利用函数关键字自定义函数(命名函数) 2. 函数表达式声明(匿名函数) ``` var fun = function(name) {console.log(name)}; fun("ygj"); // 调用函数 ``` - fun是变量名,不是函数名 - 匿名函数和声明变量差不多,只不过变量里面存的是函数 - 函数表达式可以进行参数传递 ## 2 JS的作用域和作用域链 ### 2.1 什么是JS的作用域? 代码名字(变量)起作用和效果的范围,目的是为了提高程序的可靠性,更重要的是减少命名冲突 ### 2.2 JS作用域划分 ES6之前:全局作用域和局部作用域 - **全局作用域**:整个script标签内或者是一个单独的js文件内,是全局变量的作用域 - **局部作用域(函数作用域)**:函数内部,是局部变量(在函数内声明的变量)的作用域 注意:在函数内未声明但是赋值的变量是全局变量,可以在函数外使用 ES6中添加了块级作用域,即{}作用域,如if(){}, for(){} 2.3 作用域链 1. 概念:内部函数访问外部函数的变量,采取的是链式查找的方式来决定取哪个值,这种结构称为作用域链,即**就近原则** 2. 分析方法:站在目标出发,一层一层往外找(必要时可画图辅助分析) ```js function f1() { var num = 123; function f2() { var num = 0; console.log(num); } f2(); } var num = 456; f1(); // 输出结果是0 ``` ## 3 JS的预解析 ### 3.1 js引擎运行js分两步——预解析和代码执行 1. 预解析 :js引擎会把js里面所有的var和function提升到当前作用域的最前面(变量放在更前面) 2. 代码执行:按照代码书写的顺序从上往下执行 ### 3.2 预解析分为变量预解析(变量提升)和函数预解析(函数提升) 1. **变量提升**:把所有变量声明提升到当前作用域最前面(不提升赋值操作) e.g.1 直接运行`console.log(num)`会报错,但运行下面的代码则会报undefined ```js console.log(num); var num = 10; ``` 原因就是js引擎按照变量预解析把上面代码转换成了下面的实际代码 ``` var num; console.log(num); num = 10; ``` e.g.2 运行 ```js var fun = function() {console.log("hello")}; fun(); ``` 正常,但运行 ``` fun(); var fun = function() {console.log("hello")}; ``` 则会报错函数未定义,原因也是预解析的问题。 js引擎按照变量预解析把上面代码转换成了下面的实际代码: ```js var fun; fun(); fun = function() {console.log("hello")}; ``` 2. **函数提升**:把关键字声明的函数声明提升到当前作用域最前面(不调用函数) e.g.3 如下代码可以正常执行就是js引擎执行了函数提升 ```js fun(); function fun() {console.log("hello")}; ``` ### 3.3 预解析和作用域链综合案例 案例1 ```js var num = 10; function fn() { console.log(num); var num = 20; console.log(num); } fn(); ``` 相当于 ```js var num; function fn() { var num; console.log(num); // 就近原则,undefined num = 20; console.log(num); // 20 } num = 10; fn(); ``` 案例2 ```js f1(); console.log(c); console.log(b); console.log(a); function f1(){ var a = b = c = 9; console.log(a); console.log(b); console.log(c); } ``` 相当于 ```js function f1(){ // var a = b = c = 9;相当于 var a = 9; b = 9; c = 9; b,c直接赋值没有var声明,相当于全局变量 var a; a = 9; b = 9; c = 9; console.log(a); console.log(b); console.log(c); } f1(); console.log(c); console.log(b); console.log(a); // 报错 ```