当前位置: 首页 > news >正文

【前端开发入门】JavaScript快速入门--js变量

目录

  • 引言
  • 一、为什么要定义变量
  • 二、定义变量的一些技巧
    • 1. 解构赋值
      • 1.1 Object解构赋值
      • 1.2 Array解构赋值
      • 1.3 总结规律
    • 2. 字符串拼接
  • 三、变量作用域
  • 四、总结

引言

本系列教程旨在帮助一些零基础的玩家快速上手前端开发。基于我自学的经验会删减部分使用频率不高的内容,并不代表这部分内容不重要,只是对于初学者来说没必要一开始就学的面面俱到。我希望可以先通过主干内容带大家入门前端,细节技巧性内容,可以在后续的开发工作中自行发现并掌握。

通过【前端开发入门】JavaScript快速入门–基本认识 这篇文章的讲解,我希望你已经掌握了基础的js数据类型知识以及简易调试代码的技能。

本篇主要介绍js变量的意义、简单技巧以及作用域概念。


一、为什么要定义变量

解释为什么要定义变量这件事,得先从前端开发的数据交换模式说起。除了极个别纯展示类网站,大多数网站都会动态产生一些数据并更新在页面上。

数据来源通常是:

  1. 网络请求服务器后台得来的数据。
  2. 用户输入产生的数据
  3. 代码运行逻辑中产生的数据。

数据的类型通常是:JSON、String、Number、Boolean、Object、Array、Undefined

以网络请求获取数据为例:后端因为设计逻辑的需求或者后端数据完整性规范需求,通常在给到前端数据时都会有多余的内容。前端需要通过一系列转换最终形成可用数据,呈现在页面上。在日后学习到前端框架例如vue、react等,前端所做的大部分工作都是操作数据,数据会自动和页面dom做绑定,数据变化则页面变化,无需关心如何由数据变换到页面的dom结构。

在这里插入图片描述

既然要经过一系列操作转换数据,那么就需要变量将数据截获,从而在内存中进行运算得出想要结果。
我想到了一个比较有趣的比喻:数据就是好吃的食物,双手就是变量,你本身是前端页面。你不可能手背后伸着脑袋去吃到食物,而是需要双手先接到食物,把食物掰成一口能吃下的大小,然后吃掉。


二、定义变量的一些技巧

在讲解定义变量的技巧前,先明确一个核心点
我们在编写js代码时一定要先定义后使用

错误示例:

console.log(a); // 报错: Cannot access 'a' before initialization
let a = 0;
let b = 1;
add(a, b); // 报错: Cannot access 'add' before initialization
const add = (a, b) => {return a + b;
};

修改示例:

let a = 0;
console.log(a); // 输出:0
let b = 1;
const add = (a, b) => {return a + b;
};
console.log(add(a, b));// 输出:1

1. 解构赋值

1.1 Object解构赋值

设定一个场景1:发起了一个网络请求,获取了一组JSON格式(也是一种Object)的数据,你需要取出一部分作为你定义函数的传参,然后将函数输出结果渲染到页面上。

现阶段还没介绍网络请求部分(我希望在前端框架处再说),所以我们伪造一个已经请求到的数据,

{name: "qbbmnn",redBall: 10,greenBall: 20,blueBall: 30,
}

我需要在页面中展示我的名字以及我手中 redBallgreenBall 总共有多少个

// 解构赋值只取name、redBall、greenBall
const { name, redBall, greenBall} = {name: "qbbmnn",redBall: 10,greenBall: 20,blueBall: 30,
};
// 定义处理数据函数
const handleData = (name, redBallNum, greenBallNum) => {return {name: name,allNum: redBallNum + greenBallNum,};
};
// 调用处理数据函数,传入待处理的三个变量,将函数return结果赋值给变量result
const result = handleData(name, redBall, greenBall)
// console控制台输出结果result 
console.log(result );// 输出:{name: 'qbbmnn', allNum: 30}

解释下以上代码:

  1. 通过解构赋值的方法定义了三个变量 nameredBallgreenBall,分别对应网络请求获取到数据部分属性的名称,定义的变量值即为对应的属性值。因为存在确定的属性名对应关系,所以在定义变量名时没有顺序关系,可以随意排列。例如:const { redBall,name ,greenBall }
  2. 定义了一个匿名箭头函数,并将函数赋值给变量handleData 。函数具有三个 形参 ,注意这里 形参 和调用函数时传入 实参 的区别。形参可以是任何值,因为函数可以调用多次传入不同值。实参是当前这次调用函数所需要的传值,每次调用函数所用的实参都有可能不同。实参数量可以与形参数量相同,也可以更少,两者从第一位开始匹配依次赋值,当实参数量少时,未被匹配的形参自动赋值为 undefined
  3. 使用result变量承接函数处理完成后的返回值。
  4. 输出result内容。

1.2 Array解构赋值

设定一个场景2:数据和场景1一样,现在需要将redBall刷成greenBall,greenBall刷成blueBall,blueBall刷成redBall,三者互换身份,更新数据。

// 对Object解构赋值定义redBall, greenBall, blueBall
let { redBall, greenBall, blueBall } = {name: "qbbmnn",redBall: 10,greenBall: 20,blueBall: 30,
};
// 对Array解构赋值,调换顺序
[redBall, greenBall, blueBall] = [greenBall, blueBall, redBall];
// 输出结果
console.log(redBall); // 输出:20
console.log(greenBall); // 输出:30
console.log(blueBall); // 输出:10

解释下以上代码:

  1. 通过对Object数据解构赋值定义了三个变量 redBallgreenBallblueBall
  2. 将三个变量整合为数组,重新排序,然后通过数组的解构赋值将变量重新赋值。
  3. 注意这里将定义变量时的标识符改为 let ,因为这些变量在后续操作中需要改变。
  4. 输出结果。

1.3 总结规律

从以上两个例子中我们可以得到解构赋值的一些规律

  • 针对Object类型的解构赋值。因为存在键值对的特性,每个属性都有特定的名称,我们无需关心赋值的顺序,只需要名字匹配即可。我们也不关心赋值数量问题,只取自己需要的属性。
  • 针对Array类型的解构赋值。此时为数组排列,只存在序号没有特定的属性名,所以赋值时需要按照顺序赋值,按照等号右侧的顺序依次将值赋予左侧变量。如果等号右侧值数量不够,则赋予左侧多余变量值为 undefined
  • 解构赋值意思就是等号左右两侧拥有相同的数据结构(Object或者Array),将右侧数据对应的赋值给左侧变量。

2. 字符串拼接

设定一个场景3:仍然使用场景1的数据,这次我们要展示一整段字符串,包含所有的信息。

let { name, redBall, greenBall, blueBall } = {name: "qbbmnn",redBall: 10,greenBall: 20,blueBall: 30,
};// 字符串之间通过 + 拼接内容
const message ="我是:" +name +" 我手里有:" +redBall +"颗红色球," +greenBall +"颗绿色球," +blueBall +"颗蓝色球。";
console.log(message); // 输出:我是:qbbmnn 我手里有:10颗红色球,20颗绿色球,30颗蓝色球。// 模板字符串,使用 ${变量名} 将变量插入字符串中的任意位置,模板字符串用 `` 符号(英文键盘tab上边那个键)包裹起来。
const message2 = `我是:${name } 我手里有:${redBall }颗红色球,${greenBall }颗绿色球,${blueBall }颗蓝色球。`console.log(message2); // 输出:我是:qbbmnn 我手里有:10颗红色球,20颗绿色球,30颗蓝色球。

目前将变量与字面量字符串拼接的方式,以上两种方式都可以,但是建议使用模板字符串。


三、变量作用域

变量作用域顾名思义变量起作用的区域

按照定义变量的位置可以将变量作用域划分为:全局作用域、函数作用域、块级作用域。
在我眼里变量的作用域只有两种,即全局作用域和块级作用域(不是很严谨但是很好记),判断条件为变量是否定义在 {} 符号内部。外部为全局作用域,内部为块级作用域。

举几个例子:

// 1. globalVar 定义在 {} 外部
const globalVar = "I am globalVar";// 2. 函数的 {} 从某种意义上也可以算作块级作用域的标志
function test() {const functionVar = "I am functionVar"console.log(globalVar); // 输出: I am globalconsole.log(functionVar); // 输出: I am functionVar
}
test();
console.log(globalVar); // 输出: "I am global"
console.log(functionVar); // 报错:Uncaught ReferenceError ReferenceError: functionVar is not defined// 3. 循环体的 {} 当然也被认为是块级作用域的标志
for (let i = 0; i < 10; i++) {console.log(globalVar); // 输出 * 10: "I am global"console.log(functionVar); // 报错:Uncaught ReferenceError ReferenceError: functionVar is not defined
}// 4. 极端一些你直接使用 {} 开辟一个块级作用域也是可以的。
{const blockVar = "I am blockVar"console.log(globalVar); // 输出: "I am global"console.log(blockVar); // 输出: "I am blockVar"console.log(functionVar); // 报错:Uncaught ReferenceError ReferenceError: functionVar is not defined
}// 5. 块级作用域的嵌套使用
const globalVar1 = "I am globalVar" 
{const globalVar1 = "I am globalVar reset" const blockVar = "I am blockVar"const blockFunc = () => {const globalVar1 = "I am globalVar reset once again" const blockFuncVar = "I am blockFuncVar "console.log(globalVar1); // 输出: "I am globalVar reset once again" console.log(blockVar); // 输出:"I am blockVar"console.log(blockFuncVar); // 输出: "I am blockFuncVar "}blockFunc();console.log(globalVar1); // 输出: "I am globalVar reset" console.log(blockVar); // 输出: "I am blockVar"console.log(blockFuncVar); // 报错:Uncaught ReferenceError ReferenceError: functionVar is not defined
}

由以上的例子总结出一些规律:

  • 由1、2、3、4可知,定义在全局作用域的变量在任何地方都可以访问到该变量。但是定义在块级作用域内的变量,外层的作用域(此时为全局作用域)无法访问到。
  • 由4、5可知,同一作用域内无法定义相同的变量,但是通过块级作用域的 {} 符号划分出两片作用域,那就可以分别定义相同名字的变量,例如:blockVar
  • 由5可知,变量作用域是具有嵌套效果的。内层可以访问外层变量,外层不能访问内层变量。如果多层级共同定义了同一个变量,那么采取就近原则,读取最靠近当前的作用域内定义的那个变量版本,例如:globalVar1

四、总结

以上即为js定义变量的常见内容,包含Object、Array的解构赋值以及应用场景;定义变量的作用域;虽说是基础常识,但是还是需要在实践中熟悉并掌握,使用它们成为一种习惯。

再接再厉~


http://www.mrgr.cn/news/59138.html

相关文章:

  • 小白学视觉 | PE-YOLO:解决黑夜中的目标检测难点
  • Android 9.0 修改WLAN热点名称为MAC地址后四位
  • 【TFR-Net】基于transformer的鲁棒多模态情感分析特征重构网络
  • django5入门【03】新建一个hello界面
  • vue3+vue-baidu-map-3x 实现地图定位
  • 重生之“我打数据结构,真的假的?”--3.栈和队列(无习题)
  • 红黑树(Red-Black Tree)
  • 5.Linux按键驱动-fasync异步通知
  • 《人脸表情识别可解释性研究综述(计算机学报)》
  • 如何在Linux服务器后台训练模型
  • eks节点的网络策略配置机制解析
  • 对角双差速轮AGV的动力学解算
  • 【大数据技术基础 | 实验五】ZooKeeper实验:部署ZooKeeper
  • 028_Comma_Separated_List_in_Matlab中的逗号分割列表
  • 【C++初阶】一文讲通C++内存管理
  • 数据结构与算法分析:你真的理解排序算法吗——桶排序(代码详解)
  • redis高级篇之IO多路复用select方法简介 第174节答疑
  • 基于DDPG算法的股票量化交易
  • 【项目实战】HuggingFace初步实战,使用HF做一些小型任务
  • 如何快速绘制高效的业务架构图(三步完成)
  • 【动手学深度学习】8.5 循环神经网络从零开始实现
  • 跟我学C++中级篇——volatile的探究
  • 大厂项目经理推荐的10款常用的项目管理软件值得你收藏
  • Java中TreeSet的使用
  • 代码随想录算法训练营第二十七天|Day27 贪心算法
  • 博图软件的使用(一)