批改状态:合格
老师批语:
1.字面量
比如:1 2 3 4 5 a b c
字面量都是可以直接使用的,但是我们一般都不会直接使用字面量。
编程原则, 代码中的每个数据,都应该是有意义
2.变量 let
// 变量声明 letlet num;// 声明不赋值,默认就是undefined// 第一次赋值, 初始化num = 60;// 第二次赋值, 更新/修改num = 80;// 重复声明 let num = 100; 会报错// let 禁止重复声明,它解决了var一个bug// 推荐声明的时候进行赋值let price = 99;
const APP_NAME = "在线商城";原始类型: 数值(整数和小数), 字符串, 布尔, undefined, null
typeof 操作符返回一个字符串
字符串之间使用加号进行拼装
// 三个最常用的, number, string, bool// 还有二个特殊的// undefined null// let res;// console.log(typeof res); // 返回undefined// res = null;// console.log(typeof res); // 返回 object// 为什么不返回 null,这是一个历史遗留问题// 以上5种// number, string, boolean, undefined, null// 具有单值,不可在分,它是构成复合类型的基础
引用类型, 数组, 对象, 函数 三种
const prices = [96, 45, 23, 88];// 一个变量名,price它是一组相关数据的引用,通过price可以访问到这个集合中任何一个成员// 多值console.log(prices);// 数组使用成员的索引来访问,默认从0开始, [0],[1]...叫偏移量// console.log(prices[0], prices[1]);// 数组成员, 可以是任何类型const arr = [123,"adb",true,null,[1, 2, 3, 4, 5],{ x: 1, y: 2, z: 3 },function () {console.log("Hello world");},];
(二)对象
// 对象与数组很像,区别在于它的索引是一个字符串或标识符const item1 = {// 属性: 变量在对象中叫属性name: "笔记本电脑",num: 5,price: 6699,};console.table(item1);// 使用点语法console.log(item1.name, item1.num, item1.price);// 当属性使用了非法标识符时, 必须转为字符串, json就全部采用这种语法const item2 = {"my name": "充电宝","min-price": 9.9,};console.log(item2["my name"], item2["min-price"]);// 在实际工作中, 对象与数组, 一般是结合着用const items = [{ name: "电脑", num: 2, price: 9999 },{ name: "手机", num: 5, price: 8888 },{ name: "相机", num: 1, price: 19999 },];console.table(items);
// 函数推荐使用: 动词 + 名称function getTotal(name) {return "hello, " + name;}// 使用函数的名称加一对括号console.log(getTotal("猪老师"));console.log(typeof getTotal);// 既然函数是对象,对象就有属性或方法console.log(getTotal.name);console.log(getTotal.length);
// function , 函数声明的关键字// sum1: 函数名称// (num1, num2) 参数列表, 形式参数,(形参)// (12, 34): 调用参数,实际参数(实参),与上面的参数列表中的参数一一对应function sum1(num1, num2) {let total = 0;total = num1 + num2;return total;}sum1(5, 22);
参数过多, 使用rest参数,将所有参数压到一个数组中
// 归并参数/剩余参数/不定参数,将多余的参数压到一个数组参数中// ...: 用在函数的形参中, 就是rest,归并操作,压到一个数组中function sum3(...args) {console.log(args);console.log("total =",args.reduce((p, c) => p + c));}sum3(10, 20, 30, 40, 50, 60);// ...: 用在函数的调用参数中, 就是扩展/展开, spreadconst arr = [10, 20, 30, 40, 50, 60];sum3(...arr);
(function (a, b) {console.log(a + b);})(10, 50);
// 表达式: 3+5 就是一个简单的表达式 ,必须返回一个值let add = function (a, b) {return a + b;};console.log(add(40, 50));// 使用"箭头函数"来简化"匿名函数表达式"add = (a, b) => {return a + b;};// 1.如果函数的代码只有一行, 大括号可以不写 return 也不写add = (a, b) => a + b;// 2.如果参数只有一个, 参数的括号也可以不要的add = a => a + 5;// 3.但是没有参数时, 括号必须写add = () => 10 + 5;
块作用域
{// 块作用域// if for while 都会用到let a = 1;console.log(a); // 块里面可以访问 块外面就不能访问}
全局作用域 和函数作用域 和 作用域链
<script>// 函数外面声明: 全局作用域let username = "猪老师";function demo1() {// 函数里面声明: 函数作用域// 函数里面可以访问到函数外面的变量// let username = "欧阳老师";console.log(username);// username,先在函数内部查询,如果有就直接访问// 如果没有, 就向上一个作用域查询,一级一级向上,直到查到全局作用域// 全局有username,返回查询结束, 没有username会报错// 这么一个查找过程形成的链条就叫做作用域链。// 作用域链, 查询变量用的let email = "a@php.cn";}demo1();// console.log(email); // 外面不能访问 函数里面声明的变量// 作用域是单向的// 由外向内传递可以, 但是由内向外禁止</script>
闭包
<script>// 闭包 要满足二个条件 1. 父子函数 2. 自由变量// 父函数 parent()function parent(a) {// 子函数 f()function f(b) {// b 外部参数 c 是私有变量 b,c 都是当前子函数 f 自有变量let c = 6;// a : 是子函数 f 的自由变量return a + b + c;}// 返回return f;}// 这个时候,在外部调用parent()会返回 一个函数,此时闭包就产生了console.log(parent(5));// 本来 parent()调用结束,应该将空间和参数全部释放// 但是父函数parent中的一个变量a,被 它的一个子函数正在引用着,所以不能销毁// const f1 = parent(5);// console.log(f1);// console.log(f1(1));console.log(parent(5)(1));// 经典应用, 通常与IIFE立即执行函数配合let counter = (function (n) {// 子函数// n: 自由变量, 它不属于子函数return function () {// 子函数自有变量只能有二种// 1. 外部参数, 2. 自己声明的变量return n++;};})(5899);console.log(counter());console.log(counter());</script>
<script>// 1. 属性的简化let name = "猪老师";let user = {// 对象里面也有一个 name: "猪老师",// name: "猪老师",// name: name,// 如满足以下二个条件,可以使用简化属性 直接写成 name// 1. 作用域相同: 对象属性与变量处在同一个作用域下面// 2. 名称相同: 对象属性与变量同名name,};console.log(user.name);// 2.方法的简化user = {name,// 所谓方法: 就是属性的值是一个函数// getInfo: function () {// return "我是 : " + user.name;// },// 把上面 getInfo 方法进行简化// 1.将":function"去掉// 2.在对象方法中, 尽量不要用箭头函数,除非确定你不会用到thisgetInfo() {return "我是 : " + user.name;},};console.log(user.getInfo());</script>
<script>// 在对象中,应该使用一个新变量,这个变量应该永远和当前的对象绑定// 也就是这个变量,应该是当前对象的一个引用// 这个变量就是: this 永远 指向当前对象let mobile = {name: "iPhone 13",getInfo() {// this = mobile; 这行代码应该是你的想像中的伪代码,辅助理解// this你不需要管理 ,它是由js引擎自动设置的return this.name;},};console.log(mobile.getInfo());</script>
模板字符串: 可以使用插值表达式的字符串
<script>// 传统字符串, 多行和表达式变量的混写非常的麻烦// es6使用模板字符串, 可以解决 用反引来来声明, 不用引用let lang = "html\n" + "css\n" + "js";// 改写成lang = `htmlcssjs`;let a = 10,b = 20;let res = a + " + " + b + " = " + (a + b);// 改写成// 使用 ${...} 插值占位符,可以将变量或表达式嵌入到字符串res = `${a} + ${b} = ${a + b}`;</script>
标签函数,就是在”模板字符串”之前加一个标签/标识符,而这个标签,就是一个函数名
<script>function total(strings, num, price) {console.log(strings);console.log(num, price);let res = `${strings[0]}${num}${strings[1]}${price}, 总金额: ${num * price} 元`;console.log(res);}total`数量: ${5} 单价: ${90}`;// 模板字符串参数中的占位符比较多,可以用rest进行归并// 标签函数的参数是有约定的, 不能乱写, 第一个是字面量数组,从第二起才是内部的占位符参数// 不能像函数那样加括号调用 sum()// 两个 ${} 插值占位符 中间会产生一个空字符串sum`计算多个数之和: ${5}${6}${7}${8}${9}kwgwwkwfe`;function sum(strings, ...args) {console.log(strings);console.log(`${strings[0]} ${args.join()}之和是 ${args.reduce((p, c) => p + c)}`);}</script>
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号