目录
[1. 全局变量和局部变量重名](#1. 全局变量和局部变量重名)
[2. 方法内不使用 var 定义变量对全局变量的影响](#2. 方法内不使用 var 定义变量对全局变量的影响)
[3. 变量名和参数名重复](#3. 变量名和参数名重复)
[4. 作用域链 :作用域嵌套产生的作用域父子子孙关系](#4. 作用域链 :作用域嵌套产生的作用域父子子孙关系)
[5. 嵌套作用域的变量相互访问](#5. 嵌套作用域的变量相互访问)
[1. var变量的变量提升](#1. var变量的变量提升)
[2. 声明式函数提升](#2. 声明式函数提升)
[3. 表达式函数提升](#3. 表达式函数提升)
计算机存储方式
// 计算机的软件运行时的内存使用而言,数据的存储方式主要分为两种存储区域
// 栈空间:栈空间的存储容量受限 => 读取和查找变量的速度会更快
// 堆空间:堆空间理论上容器是无限 => 存储更多数据
// 数据的存储方式
// 1. 基本类型:Number String Boolean null undefined
// 2. 引用数据类型(复杂数据类型):Array
// 变量名会被直接记录在 栈空间中,方便程序运行时的快速加载
// 变量值的存储会因为类型不同存储区域不同
// 1. 基本类型:值直接存在栈中,和变量名在一起
// 2. 引用类型:存在堆中,通过内存地址编码进行关联,栈中的变量绑定时堆中的地址
var num = 100; // 定义一个变量num 值为 100
var num1 = num; // 定义一个变量 num1 值从 num 变量获取 => 100
console.log(num,num1);
num1 = 200; // 对变量 num1 进行重新赋值,取值200
console.log(num,num1);
// 因为 = 赋值运算只操作栈
var arr = [1,2,3,4,5]; // 定义一个变量 arr ,值为 [1,2,3,4,5]
var arr1 = arr; //定义一个变量 arr1, 值从 arr 变量获取 => [1,2,3,4,5]
console.log(arr,arr1);
arr1[0] = 999;
console.log(arr,arr1); // [999,......] [999,......]
arr1 = ["a","b","c"]; // 重新赋值一个全新的数据,所有堆提供一个新的地址
console.log(arr,arr1);
// 数据不同存储方式对方法参数的影响
// 方法参数传递会因为数据类型不同,分为 值传递 和 引用传递
// 1. 值传递:将基本数据类型数据作为参数传递
// 2. 引用传递:将引用数据类型的堆地址作为参数进行传递
function printParams(a,b){
a = "新数据";
b[0] = 999;
// 重新给b赋值了一个堆的指向数组地址,此时的b和传递的arr之间没有关系了
b = [66,77,88];
b[0] = 1111;
}
var str = "abc";
var arr = [11,22,33]
console.log(str,arr); // abc [11,22,33]
// str 传递的是值 ,内部的修改不会影响到 str 变量本身 => 值传递
// arr 传递的是地址 ,内部在不修改地址的情况下会影响的 arr 变量本身 => 引用传递
printParams( str,arr )
console.log(str,arr); // abc [999,22,33]
方法的定义方式
声明式方法
function show(){
}
表达式方式方法
// => 以变量的规则声明
var printFun = function(a,b){
return a + b;
}
var res = printFun("a",123);
console.log(res);
作用域
// 作用域:代码对变量或方法使用范围的一种限制
// 让数据不会变成 脏数据
// js作用域
// 1. 全局作用域:同一个HTML加载的JS代码都可以直接访问的作用域
// 全局作用域声明的变量或者方法,在当前html的任何JS位置中都可以直接被访问
// 浏览器全局作用域实际上就是,JS提供窗口数据 window
// 浏览器加载JS时就会初始化变量值,当浏览器关闭时才会删除
// 2. 局部作用域:声明的方法的方法体
// 每个方法的方法体范围就是一个局部作用域
// 局部作用域声明的变量或方法只能在当前作用域中使用
// 局部变量只有在方法被执行时才会初始化变量值,当方法执行完成后会进行删除
// 全局变量声明 => 数据存在window上
var people = "abc";
var num = 100;
console.log(window);
// 直接使用全局变量名
console.log("同script",num);
// 通过 window.变量名 进行使用
console.log("同script",window.num);
// 局部作用
function funA(){
var count = 10;
return count;
}
// 把方法返回的结果,重新定义成一个全局变量
var a = funA();
// 受作用域限制,方法外无法直接调用方法内的变量
console.log(count);
// console.log(a);
变量作用域对代码影响
1. 全局变量和局部变量重名
var msg = "全局msg";
function printFunA(){
console.log(msg);
}
printFunA(); // 输出:全局作用域变量msg
// 就近原则
function printFunB(){
var msg = "局部msg";
// 方法内无法获取全局变量msg
console.log(msg); // 获取局部变量msg
}
printFunB(); // 输出:局部作用域变量msg
console.log(msg); // 输出:全局作用域变量msg
2. 方法内不使用 var 定义变量对全局变量的影响
// JS 变量定义时,只有具有声明符号 var 的变量表示为重新定义
// 如果变量定义时,没有使用 var ,会首先查询是否存在该变量:
// 如果存在直接使用,不存重新定义
// 如果不存在,重新定义全局变量
var info = "全局info";
function printFunC(){
info = "局部info"; // 对全局变量 info 进行覆盖
console.log(info);
}
printFunC(); // 输出:局部变量info
console.log(info); // 输出:局部变量info
function printFunD(){
text = "局部text";
console.log(text);
}
printFunD(); // 输出:局部text
console.log(text); // 输出:局部text
3. 变量名和参数名重复
var num = 1000;
function printFunE(num){
// 方法形参是存在一个 隐藏的 var 关键字,所以形参是新变量定义,形参变量属于局部作用域
console.log(num);
num = 999;
console.log(num);
}
printFunE(); // 输出:undefined , 999
console.log(num); // 输出:1000
4. 作用域链 :作用域嵌套产生的作用域父子子孙关系
var flag = false;
function printFunF(){
// 局部方法
// function printFunG(){
// console.log(flag);
// }
var printFunG = function(){
console.log(flag); // 查找到了全局的 flag
}
printFunG(); // 输出:false
}
printFunF(); // 输出:没有任何输出
// printFunG(); // 输出:报错 => 全局没有该方法
var name = "张三";
function printFunH(){
var name = "李四";
function printFunI(){
console.log(name);
}
printFunI(); // 输出:李四
}
printFunH();
5. 嵌套作用域的变量相互访问
function printFunJ(){
var argA = "printFunJ-argA-变量";
function printFunK(){
var argB = "printFunK-argB-变量"
console.log(argA);
}
printFunK(); // 输出:printFunJ-argA-变量
console.log(argB); // 输出: 报错
}
printFunJ();
js预解析
// 预解析:浏览器先完成JS加载,加载完成后会进行运行
// 加载的过程中,JS解析器会对一些特殊结构代码进行调整,保证浏览器正常运行
1. var变量的变量提升
// console.log(msg); // 报错 ReferenceError: msg is not defined
// 被提升的info
// var info;
console.log(info); // undefined => 触发预解析 //16行
var info = "测试数据"; //18行
// 预解析 发现 16 使用了 18 的变量
// 将18行的变量拆分成两部分:var info; info="测试数据";
// 将声明提升到 16 之前定义;
// info = "测试数据"; // 拆分后的赋值
function showFun(){
// 变量提升也受 作用域限制
console.log(text);
var text = "text变量";
}
showFun();
// console.log(text);
2. 声明式函数提升
// 声明式函数是一个整体语法,不能拆分的
// testFun(); // ReferenceError: testFun is not defined
printFunA(); 39行
// 因为是声明式函数,代码解析式,发现39需要调用41行代码,41行的方法代码会被整体提前
function printFunA(){
console.log("printFunA方法");
}
3. 表达式函数提升
printFunB(); // TypeError: printFunB is not a function
// 代码解析式,发现47需要调用49行代码,
// 49行被分解成 var printFunB; printFunB = function(){......}
// var printFunB 被提升到47行之前
// 提升后的变量没有被赋值,默认值是undefined,不是一个方法,不能被()调用,所以47行报错
var printFunB = function(){
console.log("printFunB方法");
}
对象
// 对象:是一组无序的相关属性和方法的集合
// 是一种代码中定义的数据格式,用于统一记录物品或者事物的相关信息
// var car = ["发动机","车架","轮子"];
// console.log( car[1] );
// 字面量对象定义:
/*
key 自定义对象属性名称 = 变量声明
value 属性的取值 = 变量赋值 var 对象名 = {
key:value,
key1:value1,
......
};
*/
javascript
var car = {
motor:"四缸发动机",
frame:"铝合金",
seat:"真皮"
};
// 对象的取值 对象变量名称.对象属性名
console.log( car.motor );
var stu = {
no:10001,
name:"tom",
age:23,
sex:"男"
}
console.log( stu.name );
console.log( stu.age );
console.log( stu.sex );
var songList = [
// 存储很多歌曲
{
img:"http://p1.music.126.net/WCE6Za49yYQyDvnNJykJ-w==/109951170209787177.jpg?param=140y140",
count:4399,
name:"我的歌声1",
singer:"张三1"
},
{
img:"http://p1.music.126.net/WCE6Za49yYQyDvnNJykJ-w==/109951170209787177.jpg?param=140y140",
count:3000,
name:"我的歌声2",
singer:"张三2"
},
{
img:"http://p1.music.126.net/WCE6Za49yYQyDvnNJykJ-w==/109951170209787177.jpg?param=140y140",
count:200,
name:"我的歌声3",
singer:"张三3"
},
{
img:"http://p1.music.126.net/WCE6Za49yYQyDvnNJykJ-w==/109951170209787177.jpg?param=140y140",
count:6666666,
name:"我的歌声4",
singer:"张三4"
},
{
img:"http://p1.music.126.net/WCE6Za49yYQyDvnNJykJ-w==/109951170209787177.jpg?param=140y140",
count:200,
name:"我的歌声3",
singer:"张三3"
},
{
img:"http://p1.music.126.net/WCE6Za49yYQyDvnNJykJ-w==/109951170209787177.jpg?param=140y140",
count:666,
name:"我的歌声4",
singer:"张三4"
}
];
// console.log( songList[1].name );
for (var i = 0; i < songList.length; i++) {
// console.log( songList[i] );
// console.log( songList[i].img );
document.write("<div class='box'>")
document.write(`<img src="${songList[i].img}">`)
// console.log( songList[i].count );
var num = parseInt( songList[i].count/10000);
var temp = num>1 ? num+"万":songList[i].count
document.write(`<div>播放量:${ temp }</div>`)
// console.log( songList[i].name );
document.write(`<div>名字:${songList[i].name}</div>`)
// console.log( songList[i].singer );
document.write(`<div>演唱者:${songList[i].singer}</div>`)
document.write("</div>")
}