基础了解
- 在JavaScript中, 指令被称为语句, 并以分号 (;) 结尾, 也就是每一行代码
- 虽然非必须, 但这是一个良好的编程习惯
JavaScript中区分大小写, 且使用的是Unicode字符集
单行注释 //
- 多行注释 /**/
-
变量(基本类型和引用类型)声明
声明的三种关键字
var 声明局部变量和全局变量, 可选初始化一个值, 下面有对 var 和 let 的差异进行讨论
- let 声明一个块级作用域的局部变量, 可选初始化一个值, 正是因为var定义的都是全局变量的巨大隐患而且为了其他版本的兼容, 才搞了个新关键字 let
const 声明一个块级作用域的只读量(或者说常量), 并非全局作用域哦
变量是什么?
在JavaScript中, 变量就是值的符号名, 可以看成房子的名字
- 变量也被叫做标识符
- 事实上, 只要是Unicode字符集里面的字符基本都可以拿来当标识名, 但不合法, 比如 let 好的 = “good”
变量标准的命名规则应该是以字母、下划线 (_) 或者美元符号 ($) 开头; 后续的字符也可以是数字, 比如name, _name, $name
声明变量的形式
var x = 25
- x = 25 严格模式下, 会报错, 不推荐这么写
-
var 和 let 声明变量的区别
let存在暂时性死区, 因此使用 let 声明的变量不存在变量提升, 且其变量也不能重复声明- 应该这样理解: let 存在变量提升, 但 let 也具有暂时性死区, 这使得该变量调用不能发生在声明之前, 所以let表现出来的结果便是不存在变量提升
- 而使用 var 声明的变量没有这样的考虑
所谓暂时性死区, 便是在变量声明这一行之前, 调用到该变量便会报错, 而变量提升便是调用不报错, 从这个角度看, 暂时性死区与不存在变量提升是一个意思
变量的初始化
使用 var 和 let 声明变量不赋值的话, 会被分配一个 undefined 的值, 其意为未定义的
- 如果使用一个未声明的变量的话, 系统会报引用类型的错误, 注意不要和前面的暂时性死区概念混淆
同样的, 当我们想知道一个变量是否被赋值, 我们可以通过该变量是否等于 undefined 来判断
变量的作用域
这可能就是 let 和 var 最大的区别 —— 作用域的划分界限
- 在JavaScript中, 变量的定义域一开始并不是以代码块划分界限的, 而是以函数划分的, 如果一个变量在函数内被定义, 函数之外的地方便是不可见的, 也就是说 if 和 for 这种代码块中定义的变量并不是作为局部变量来看待的 ```javascript // Es6 之前, 没有 let 关键字的时候
if(true) { x = 5 // 内部默认为 var x = 5 }
for(i = 0; i<1 ; i++) { y = 5 }
function f1() { z = 5 }
f1() console.log(‘x=’, x, ‘, y=’, y, ‘, z=’, z) // x=5, y=5, z is nodefined
- Es6标准后, let 的出现使得之前的划分形式有了改变. let 以代码块作为作用域划分界限, 与之前的 var 有了根本性的区别, 而let也使得程序员在理清 if 或是 for 这种代码块时更好理解(其中可能也有后端转型过来易理解的考量)```javascript// Es6之后, 有 let 关键字if(true) {let x = 5}for(i = 0; i<1 ; i++) {let y = 5}function f1() {let z = 5}f1()console.log('x=', x, ', y=', y, ', z=', z) // x, y, z are nodefined
变量提升
- 通俗来说, 就是先上车后补票
- 在使用 var 声明变量的时候, 你可以先把该变量拿去操作, 也就是操作在声明之前 ```javascript x = 3 console.log(‘x=’, x) // x=3
var x
- 在JavaScript中, 使用 var 定义的变量会先被提升到该作用域顶部, 用上面来举例那就是4->1->2- **使用 let 关键字也具有变量提升的效果, 但结果不同, let 声明的变量同样会被提升到作用域顶部, 但该变量具有暂时性死区, 即在该变量声明那一行之前, 对其相关调用都会抛出引用错误**- 变量提升虽然方便, 但容易让阅读者逻辑混乱, 我们更强调逻辑的连贯性- 变量提升只是单纯把声明提升到作用域顶部, 并不提供在提升的同时赋值的功能```javascriptconsole.log(x) // x is undefinedvar x = 5
函数提升
- 对于函数来说, 只有函数声明会被提升到顶部, 而函数表达式不会, 如下 ```javascript // 函数声明形式
foo() // 正常执行
function foo() { alert(‘1. Good!’) }
// 函数表达式形式
baz() // 报错, baz is not defined
var baz = function () { alert(‘2. Good!’) }
- 分析: ~~就像变量提升最后说的, 并不提供提升的同时赋值的行为, 所以此时的baz应该是undefined~~, 事实却是baz is not defined (未定义), 那应该是内部对函数表达式有另外的处理, 因此要和变量提升分开考虑<a name="bv18K"></a>## 全局变量- 即为全局对象的属性, 而全局对象可以通过globalThis获取- 在默认网页中, 全局对象为 window, 可以使用 window.variable 的语法来设置和访问该变量- 在node中, 全局对象则是 global- 不使用关键字声明的变量也被视为全局变量```javascript(function (){x = 5;console.log('1. x=', x); // x=5})()console.log('2. x=', x); // x=5, 使用 var, let的话, 这里会报错
常量(Constants)
- 使用关键字 const 创建的一个只读量, 命名规则与变量相同: 必须以字母/下划线 (_) /美元符号 ($) 开头并可以包含有字母/数字/下划线, 注意常量名不能与变量名/函数名相同
- 常量在声明时一定要进行初始化, 且在该值作用域中不可更改
- 常量的作用域划分界限与 let 定义的变量相同, 都是以代码块为界限
当将引用类型赋值给常量时, 其内部变化是不收保护的, 就是说可以改变的
const My_OBJ = {name : 'JavaScript'}My_OBJ.name = 'Good' // 并不会报错
如果真要将引用类型赋值给常量的话, 要使用Object.freeze()方法冻结对象, 或是启用严格模式 ```javascript const obj = { prop: 42 };
Object.freeze(obj);
obj.prop = 33; // 报错
<a name="Ol6BO"></a># 数据结构和类型<a name="mFTA4"></a>## 数据类型- 基本数据类型: null(空型), undefined(未定义型), boolean(布尔型), int(整型), string(字符串型), symbol(符号型)- 引用数据类型: array(数组), function(函数), object(对象)<a name="BNQQM"></a>## 数据类型的转换- **JavaScript是一种弱类型语言, 或者说动态类型语言, 也就是不拘于类型, 不必指定类型, 变量的值不受类型的约束**- 这里提一下, 我们老师也说JavaScript应该是泛型编程语言, 不会拘束于面向对象, 还是面向过程, 解决问题才是关键```javascriptvar x = 25x = 'Good Good study'x = falsex = 1.252x = {name: 'ming', age: 18}
- 注意: 加号 (+) 在其中的作用, 在数值环境时, +做为加法运算使用, 而在字符串环境时, +作为字符串拼接符号使用, 当两种情况均存在时, 以字符串拼接为准, 数值会变成字符串形式 ```javascript x = 25 y = 10 z = ‘good good ‘ w = ‘study’ console.log(x+y) // 35 console.log(z+w) // ‘good good study’ console.log(x+z) // 25good good
- 这里说一下字符串转换为数值的方法, parseInt()[丢失小数部分, 返回整数, 默认十进制]和parseFloat(), 截取值为从头开始的数值部分```javascriptstr01 = '123abc123'str02 = 'abc123abc'str03 = '1.20551'console.log(parseInt(str01)) // 123console.log(parseInt(str02)) // NaNconsole.log(parseInt(str03)) // 1console.log(parseFloat(str03)) // 1.20551
undefined 在各环境下, 内部进行的处理
- 在布尔环境中, undefined 会被视为 false, 也就是说 !undefinedNum == true
在数值环境中, undefined 则会被视为 NaN(not a number)
undefined 和 null 的区别
null 表示没有对象, 该处不应该有值, 或者说终点的意思, 没有了, 结束了
- null 表示这个房子不能住人了
- undefined 表示缺少值, 该处有值, 但未定义, 还没结束, 但也还没有开始
- undefined表示这个房子还没住人
- 在两者概念方面, 我也懵逼, 希望有好心人帮忙😁
- null 在数值环境和布尔环境中默认看做为0, 所以 !nullValue == true (true), nullValue+2 == 2 (true)
注意 nullValue == undefined (true), nullValue === undefined (false), 两者都是独立基本类型
字面量(Literals)
基础意思
在JavaScript中, 字面量是常量, 其值固定, 而且在脚本中不可更改, 比如false, 3.1415 — MDN
- 看了一些资料, 描述的跟鬼一样, 在我看来应该是表达方式的意思吧, 像数组的字面量就是数组, 那数组是怎么表示的呢, 就是 [1, 2, 3] 这样的; 像布尔字面量true和false; 像是字符串字面量就是用单引号/双引号括起来的句子, 比如”good”/‘nice’这样的
-
数组字面量/数组
var arr = ['firefox', 'google', 'edge']
数组元素可以是任一类型, 注意的是数组本身就是一种类, length就是数组实例的属性
- 注意数组中的逗号问题, 当元素1与元素2之间存在多余的逗号时, 该内存空间会被创建, 值为undefined ```javascript var arr01 = [‘good’, , , ‘study’] var arr02 = [‘good’, ‘study’, ,]
console.log(arr01.length) // 3 console.log(arr01[1]) // undefined console.log(arr02.length) // 2, 逗号在末尾时会被省略
- **显式地将缺失的元素声明为undefined, 将大大提高你的代码的清晰度和可维护性** -- MDN, 我未理解<a name="mBO73"></a>## 布尔字面量/布尔值- 布尔类型具有两种字面量 false/true- 不要混淆布尔对象的真与假和布尔类型的原始值 false/true, 布尔对象是对布尔类型的一个包装器 -- MDN, ???<a name="WOZMf"></a>## 整数字面量/整数- 整数字面量就是整数. 整数可以用十进制, 八进制, 十六进制, 二进制表示- 十进制: 1, 2, 3- 八进制: 015, 07, 01(严格模式下, 必须以0o/0O开头)- 十六进制: 0x15, 0xFF, 0X1- 二进制: 0b101, 0b100, 0B001<a name="lnPVk"></a>## 浮点数字面量/浮点数- 组成部分为:- 十进制整数- 小数点- 小数部分(也是十进制数)- 指数部分(e±十进制数)- 如3.141, 2.14e+10, 1.24e-2<a name="FyiwE"></a>## 对象字面量/对象- 对象字面量就是在一对花括号内的零个或多个键值对的列表, 如下```javascriptlet obj = {name: 'ming',age: 18,sex: 'nan',dept: 'game'}
- 我们不能在一行的开头就使用花括号, 这样左花括号会被识别为是一个代码块的起始
对象中的键名可以是Unicode字符集的任意组合, 注意键名不合法的话, 调用时必须使用object[“键名”]的形式, 而不能使用object.key的形式
let obj = {"game": 'ming', // obj["game"]年龄: 18, // obj["年龄"]_sex: 'nan', // obj["_sex"]4: 'game', // obj[4]/obj["4"], 因为对象不使用下标记录, 所以直接使用也没事"": 'good good study', // obj[""]"!": 'day day up' // obj.["!"]}
ES6增强的对象字面量内容
使用两条正斜杠括起来的内容就是
var reg = /123456/
字符串字面量
用单引号/双引号括起来的零个或多个字符
可以在字符串字面量上使用字符串对象的所有方法 — JavaScript内部会将字符串字面量转化为临时字符串对象, 调用完方法后, 该临时对象就会被废弃
console.log("John's cat".length) // 10
ES6中, 新增了一种模板字符串, 通过使用反引号``来表示, 不仅可以跨越行数, 也可以进行插值, 保证代码阅读的连贯性 ```javascript let name = ‘John’
let str = ${name} is cat,
to be or not to be
```
- 字符串中可以使用的一些特殊字符(转义字符) — MDN | \0 | Null字节 | | —- | —- | | \b | 退格符 | | \f | 换页符 | | \n | 换行符 | | \r | 回车符 | | \t | Tab (制表符) | | \v | 垂直制表符 | | \‘ | 单引号 | | \“ | 双引号 | | \\ | 反斜杠字符(\) | | \XXX | 由从0到377最多三位八进制数XXX表示的 Latin-1 字符。例如,\251是版权符号的八进制序列。 | | \xXX | 由从00和FF的两位十六进制数字XX表示的Latin-1字符。例如,\ xA9是版权符号的十六进制序列。 | | \uXXXX | 由四位十六进制数字XXXX表示的Unicode字符。例如,\ u00A9是版权符号的Unicode序列。见Unicode escape sequences (Unicode 转义字符). | | \u{XXXXX} | Unicode代码点 (code point) 转义字符。例如,\u{2F804} 相当于Unicode转义字符 \uD87E\uDC04的简写。 |
