【javaScript】基础梳理
简介
- javascript不仅可以在浏览器端执行,也可以在服务端执行,甚至可以在任何装载了javascript引擎的设备中执行
- 不同的引擎有不同的代号,比如chrome,Opera和edge的引擎v8,Firefox的引擎SpiderMonkey
- 引擎的工作原理:读取脚本,将脚本解析成计算机语言(编译),然后机器执行代码,引擎会对每个流程进行优化
浏览器中的javascript
浏览器中的js能给网页添加或修改内容,响应用户行为,向远程服务器发送请求,下载上传文件,设置读取cookie,记住客户端数据等,但需要注意,出于对用户信息安全,浏览器js的能力是受限的,这是为了防止恶意获取用户信息或损害用户数据,所以浏览器中的js读、写、复制和执行硬盘上的任意文件,它没有直接访问操作系统的功能,浏览器是允许对文件进行一些相关操作的,但也是受限的,需要用户做出特定的行为,比如拖放文件,用过input选择文件,总之是需要获得用户明确许可的,此外,不同窗口之间(不同源)是不能通信的,这也是为了用户信息的安全
script
- 一般来说,只有最简单的脚本才嵌入到 HTML 中。更复杂的脚本存放在单独的文件中,使用独立文件的好处是,浏览器会下载它,然后将它保存到浏览器的缓存中,之后其他页面想要相同的脚本就会从缓存中获取,而不是下载它。所以文件实际上只会下载一次,这可以节省流量,并使得页面更快
- script指定了src,标签内容就会被忽略,所以script不能同时有src和内部代码
alert、prompt 和 confirm
- alert显示信息,prompt显示信息要求用户输入文本。点击确定返回文本,点击取消或按下 Esc 键返回null,confirm显示信息等待用户点击确定或取消。点击确定返回 true,点击取消或按下 Esc 键返回 false
- 这些方法都是模态的,它们暂停脚本的执行,并且不允许用户与该页面的其余部分进行交互,直到窗口被解除
- 模态窗口的确切位置由浏览器决定。通常在页面中心,外观也是由浏览器决定的,我们不能修改它
数据类型
javascript有八大数据类型,前七种为基本数据类型(原始数据类型),而object为复杂数据类型 原始数据类型:
- number:用于任何类型的数字:整数或浮点数,在 ±(253-1) 范围内的整数
- bigint:用于任意长度的整数
- string:字符串
- boolean: 用于 true 和 false
- null: 用于未知的值
- undefined:用于未定义的值
- symbol:用于唯一的标识符 复杂数据类型:object 用于更复杂的数据结构
typeof
typeof 运算符查看存储在变量中的数据类型,在使用 typeof
运算符时,有几个注意事项需要注意:
typeof null
返回"object"
: 这是一个历史遗留问题,typeof null
返回"object"
,而不是"null"
。这是因为在 JavaScript 的早期版本中,将null
值的类型标识为对象类型,但实际上null
是一个原始值,表示一个空对象指针。因此,当使用typeof
操作符检查null
时,需要额外注意。typeof
无法区分数组和对象: 当使用typeof
操作符检查数组时,返回的结果是"object"
,而不是"array"
。这是因为在 JavaScript 中,数组是对象的一种特殊形式。如果需要判断一个值是否为数组,可以使用Array.isArray()
方法来进行准确的判断。typeof
对于函数返回"function"
: 当使用typeof
操作符检查函数时,返回的结果是"function"
。这可以用来区分函数和其他类型的值。typeof
对于未声明的变量返回"undefined"
: 当使用typeof
操作符检查未声明的变量时,返回的结果是"undefined"
。这可以用来检查变量是否已经声明。typeof
返回的都是字符串:typeof
操作符返回的结果都是字符串,即使操作数是一个对象、函数或其他类型的值。这是因为typeof
是一个一元运算符,总是返回一个字符串值。
判断数据类型总结:
基本类型使用typeof即可,对于对象数组和函数,使用
Object.prototype.toString.call()
Object.prototype.toString.call([])=====>[object Array]
Object.prototype.toString.call({})=====>[object Object]
Object.prototype.toString.call(()=>{})====>[object Function]
运算符运算元
运算元,一元运算符,二元运算符的定义
运算符作用的对象叫做运算元,比如表达式5 * 2
,该表达式就有两个运算元,5跟2,如果一个运算符对应的只有一个运算元,那么它是 一元运算符。比如说一元负号运算符-
;如果一个运算符拥有两个运算元,那么它是 二元运算符。减号还存在二元运算符形式
let a = 1;
a = -a; //一元运算符
console.log(a) //-1
let x = 1, y = 2;
console.log(x - y) //二元运算符
运算符优先级
关于运算符的优先级,记住一句话:一元运算符先于二元运算符作用于运算元,赋值运算符优先级非常低,在 JavaScript 中,所有运算符都会返回一个值。这对于加减乘除来说是显而易见的,但对于 = 来说也是如此,比如语句x = value
将值 value 写入 x 然后返回 value
let a = 1;
let b = 2;
let c = 3 - (a = b + 1);
自增自减
分为前置自增自减++count
和后置自增自减count++
,两者区别就在于返回值,所有运算符都有返回值,前置返回值是返回最新的,而后置是返回原来的值
let counter = 1;
let a = ++counter;
alert(a); // 2
let counter = 1;
let a = counter++;
alert(a); // 1
自增自减优先级比绝大部分的算数运算符优先级要高
let a = 1;
let b = 1;
alert(2 * ++a); //4
alert(2 * a++); //2
总结:如果自增/自减的值不会被使用,那么两者形式没有区别,如果我们想要对变量进行自增操作,并且需要立刻使用自增后的值,那么我们需要使用前置,如果我们想要将一个数加一,但是我们想使用其自增之前的值,那么我们需要使用后置
逗号元算符
逗号运算符能让我们处理多个表达式,每个表达式都运行了,但是只有最后一个的结果会被返回
let a = (1+2,3+4);
alert(a); //7
类型转换与运算符易错
"4px" - 2 = NaN
//减法运算符需要数字类型的运算元,所以会将"4px"转换为数字,由于字符串中包含非数字字符"px",无法将其转换为有效的数字,所以结果为NaN,NaN转为数字为NaN,NaN-2=NaN
" -9 " - 5 = -14
//字符串转为数字时会忽略首尾空格
" \t \n" - 2 = -2
//在表达式 " \t \n" - 2 中,字符串 " \t \n" 包含了空格、制表符和换行符。这些字符在转换为数字时会被忽略,所以该表达式被解释为0,0-2=-2
null + 1 = 1;undefined + 1 = NaN;
//null 经过数字转换之后会变为 0,undefined 经过数字转换之后会变为 NaN
值的比较
- 在比较字符串的大小时,JavaScript 会使用字典或词典顺序进行判定,所以字符串是按字符(母)逐个进行比较的,比如
"2" > "12"
为true,因为首位字符"2"
大于"1"
,"apple" > "pineapple"
为false,因为"a"
比"p"
小 - undefined 和 null 在相等性检查 == 中不会进行任何的类型转换,它们有自己独立的比较规则,所以除了它们之间互等外,不会等于任何其他的值,比如
undefined == null
为true,null == 0
为false,都知道null转为数字为0,但null除了与自身和undefined,不会等于其他值 - NaN 是一个特殊的数值型值,它与任何值进行比较都会返回 false
- 在使用 > 或 < 进行比较时,需要注意变量可能为 null/undefined 的情况。比较好的方法是单独检查变量是否等于 null/undefined
空值合并运算符??
空值运算符是获取两者中第一个已定义的值
a ?? b结果: 如果a是已定义的,则结果为a; 如果a不是已定义的,则结果为b
??与||的区别
||返回第一个真值,??返回第一个已定义的值,即||无法区分false,0,空串和null/undefined,他们都是假值,但在实际中,可能只想在null或者undefined时(即当该值未知或者未被设置时)使用默认值
注意:js禁止??和&&、||一起使用,除非使用了括号明确指定了优先级
循环
while循环,当condition为真时执行循环体
while(condition){
循环体
}
do..while循环
do{
循环体
}while(condition)
先执行循环体,然后检查condition,为真时再接着执行循环体 for循环
for(begin;condition;step){
循环体body
}
示例:
for(let i = 0; i < 3; i++){
alert(i);
}
语句段 | ||
---|---|---|
begin | let i = 0 | 进入循环时执行一次 |
condition | i < 3 | 在每次循环迭代之前检查,如果为 false,停止循环。 |
body | alert(i) | 条件为真时,重复运行。 |
step | i++ | 在每次循环体迭代后执行。 |
break/continue
js允许我们通过break
跳出整个循环,break
与continue
的区别在于,continue
不会停掉整个循环,而是停止当前这次的迭代,并强制启动下一轮的循环
for(let i = 10; i < 14; i++) {
if(i % 2 == 0) break;
console.log(i);
}
上述代码当i为偶数时跳出了整个循环,所以只打印了11
for(let i = 10; i < 14; i++) {
if(i % 2 == 0) continue;
console.log(i);
}
换成continue,当i为偶数时跳出了本次循环并启动了下一轮循环,所以打印了11,13
如何跳出多层嵌套的循环?
有时我们需要从多层嵌套的循环中跳出来,这需要借助标签来实现这一功能
标签语法:
labelName: for(...) {...}
break <labelName>
语句跳出循环至标签处,看下面代码:
for(let i = 1; i<=2;i++){
console.log('outer')
for(let j = 20;j<22;j++){
if(j%2 != 0) break;
console.log(i+j)
}
}
比如该段循环,当j为偶数时才输出,奇数时跳出里层循环,外层循环还继续着,所以打印了outer、21、outer、22
outer:for(let i = 1; i<=2;i++){
console.log('outer')
for(let j = 20;j<22;j++){
if(j%2 != 0) break outer;
console.log(i+j)
}
}
加上标签,这样当j为奇数时,就会跳出最外层循环,所以打印结果为,outer、21
注意:非表达式的语法结构不能与三元运算符 ? 一起使用,所以禁止break/continue 在 ‘?’ 的右边,比如(i > 5) ? alert(i) : continue;是不被允许的
break/continue
支持循环前的标签。标签是break/continue
跳出嵌套循环以转到外部的唯一方法
转载自:https://juejin.cn/post/7275532902942244899