Skip to content

ECMAScript语法

位置一:HTML代码行内(不推荐)

Section titled “位置一:HTML代码行内(不推荐)”
<a href="javaScript:alert('执行js')" >点击执行</a>
<a onclick="javaScript:alert('执行js')">点击执行</a>

在浏览器不支持JavaScript的时候, 那么我们需要给用户提示,开启javascript

<!--在浏览器
浏览器不支持脚本;
浏览器对脚本的支持被关闭。
的情况下会显示-->
<noscript>
<p>您的浏览器不支持或者关闭javaScript运行</p>
</noscript>

注意一: javascript元素不能写成单标签

Section titled “注意一: javascript元素不能写成单标签”
  • 在外联式引用 js 文件时,script标签中不可以写JavaScript代码,并且script标签不能写成单标签;
  • 即不能写成<script src="index.js"/>;,因为这样的写法并不是所有浏览器都支持的
  • 最好引用js外部文件的时候都使用双标签
  • 在以前的代码中,<script>标签中会使用 type=“text/javascript”;
  • 现在可以不写这个代码了,因为JavaScript 是所有现代浏览器以及 HTML5 中的默认脚本语言;
  • 作为HTML文档内容的一部分,JavaScript默认遵循HTML文档的加载顺序,即自上而下的加载顺序;
  • 推荐将JavaScript代码和编写位置放在body子元素的最后一行(个人比较喜欢放在body标签的后面);
  • script标签放在 body 标签的后面浏览器解析的时候还是会把 script 标签放到body 里面

注意四: JavaScript代码严格区分大小写

Section titled “注意四: JavaScript代码严格区分大小写”
  • HTML元素和CSS属性不区分大小写,但是在JavaScript中严格区分大小写;
  • 后续补充:script元素还有defer、async属性,我们后续再详细讲解。

javaScript有如下和用户交互的手段:

交互方法方法说明方法说明
alert一个参数:变量弹出对话框
console.log多个参数:变量控制台打印输出语句
document.write参数多个:都可以写入浏览器网页
prompt参数1个:String接收用户输入的参数,返回给变量 var result = prompt(“请输入你的名字: ”);

五、JavaScript语句和分号(重点)

Section titled “五、JavaScript语句和分号(重点)”

js语句是向浏览器发出的指令,通常表达一个操作或者行为(Action)。

语句英文是Statements;

比如我们前面编写的每一行代码都是一个语句,用于告知浏览器一条执行的命令; 通常每条语句的后面我们会添加一个分号,表示语句的结束: 分号的英文是semicolon

  • 当存在换行符(line break)时,在大多数情况下可以省略分号;
  • JavaScript 将换行符理解成“隐式”的分号;
  • 这也被称之为自动插入分号(an automatic semicolon);
  • 推荐:
    • 前期在对JavaScript语法不熟悉的情况推荐添加分号;
    • 后期对JavaScript语法熟练的情况下,任意!

javaScript的注释主要分为三种:

  • 单行注释
  • 多行注释
  • 文档注释:vscode中内置文档注释插件
    • 快捷方式/**+回车
/**
* 和某人打招呼
* @param {string} name 姓名
* @param {number} age 年龄
*/

变量的声明:在JavaScript中声明一个变量使用var关键字(variable单词的缩写)(后续学习ES6还有let、const声明方式)

声明变量的时候不会确定变量的类型,在程序运行过程中通过你的值来进行判断的

js拥有动态类型,意味着变量可以用作不同的类型

  • 变量声明方式3种
var flag
flag=1
var name = 123
console.log(name)
// 同时声明多个变量 转换es5 源码中使用
var age=18 ,addr="上海"
console.log(age,addr)
  • 如果没有使用var也可以声明变量,但是不推荐因为不规范(事实上会被添加到window对象上),使用var声明的全局变量也会添加到window对象上 就算在函数中不使用var 声明变量也会被放到全局变量中
    • 慢慢的已经被抛弃了,设计的缺陷
    • es6 let定义的变量不会放到 window对象里面
  1. 变量名不能使用数字短横线分割符 - 开头和链接变量进行声明
  2. 可以使用是 字母、下划线( _ )、美元符号( $ )
  3. 不能使用关键字和保留字命名:
  4. 变量严格区分大小写
  5. 类名首母大写
  6. 方法名首字符小写,使用驼峰标记法
  7. 常量全部大写使用_下划线隔开
// 规则: 必须遵守
// 规范: 建议遵守
// 1.多个单词, 建议使用驼峰标识(小驼峰)
// 小驼峰(currentTime)/大驼峰(CurrentTime)
// 2.推荐=的左右两边加上空格
var currentTime = "16:18"
var currentPrice = "¥100"

8.3、练习:借助于第三个变量完成交换

Section titled “8.3、练习:借助于第三个变量完成交换”
// 方法二: 不借助于第三个变量完成交换(了解, 笔试面试题)
console.log("交换前, num1, num2:", num1, num2)
num1 = num1 + num2 // num1: 30, num2: 20
num2 = num1 - num2 // num1: 30, num2: 10
num1 = num1 - num2 // num1: 20, num2: 10
console.log("交换后, num1, num2:", num1, num2)

9.1、JavaScript 中有 8 种基本的数据类型(7 种原始类型和 1 种复杂类型)

Section titled “9.1、JavaScript 中有 8 种基本的数据类型(7 种原始类型和 1 种复杂类型)”
  1. Number

    • NaN:is not null;
    • infinite
  2. String

  3. Boolean

  4. Undefined:未定义

  5. Null:空对象 转换成Number的时候为0,但是与Number的0 不相等

    null隐式转换之后为0 但是类型还是Object的

  6. Object

  7. BigInt 用于任意长度的整数。

  8. Symbol 用于唯一的标识符。

因为 ECMAScript 的类型系统是松散的,所以需要一种手段来确定任意变量的数据类型。

  • 对一个值使用 typeof 操作符会返回下列字符串之一:

    1. “undefined”表示值未定义;

    2. “boolean”表示值为布尔值;

    3. “string”表示值为字符串;

    4. “number”表示值为数值;

    5. “object”表示值为对象(而不是函数)或 null;

    6. “function”表示值为函数对象;

    7. “symbol”表示值为符号;

    • typeof()的用法:
  • 你可能还会遇到另一种语法:typeof(x),它与 typeof x 相同;

    typeof是一个操作符,并非是一个函数,()只是将后续的内容当做一个整体而已;

    用来放表达式的实际上还是一个操作符

10.1、Number类型(官方叫法-数字型)

Section titled “10.1、Number类型(官方叫法-数字型)”

number 数字型-代表整数和浮点数。如120,120.3 默认值是:0

除了常规的数字,还包括所谓的“特殊数值(“special numeric values”)”也属于Number类型(了解)

  • Infinity:代表数学概念中的 无穷大 ∞,也可以表示-Infinity;
    • 比如 1/0 得到的就是无穷大;
  • NaN:NaN 代表一个计算错误,它是一个错误的操作所得到的结果;
  • 比如 字符串和一个数字相乘;

8进制前面加0o,16进制前面加0x2,2进制0b

// 3.进制表示
var num3 = 100 // 十进制
// 了解
var num4 = 0x100 // 十六进制
var num5 = 0o100 // 八进制
var num6 = 0100 // 八进制
var num7 = 0b100 // 二进制
console.log(num4, num5, num6num7)
  • 最小正数值:Number.MIN_VALUE,这个值为: 5e-324,小于这个的数字会被转化为0
  • 最大正数值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308
  • 用于判断该值能否转化为数字类型。不能转数字返回true,是可以转换为数字返回false。
  • isNaN(parseInt(123.4px))
  • 就是说判断是不是一个NaN类型的

JavaScript 中的字符串必须被括在引号里,有三种包含字符串的方式。

  • 双引号:“Hello”
  • 单引号:‘Hello’
  • 反引号(模板字符串):Hello
  • 前后的引号类型必须一致
    • 如果在字符串里面本身包括单引号,可以使用双引号;
    • 如果在字符串里面本身包括双引号,可以使用单引号;

指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。

转义字符表示符号
\'单引号
\"双引号
\\反斜杠
\n换行符
\r回车符
\t制表符
\b退格符

操作一:字符串拼接,通过+运算符

操作二:获取字符串长度 str.length ,获取的是字符串属性

布尔(英语:Boolean)是计算机科学中的逻辑数据类型,以发明布尔代数的数学家乔治·布尔为名。

只有两个值:true false 等价与1,0

Undefined 类型只有一个值,就是特殊值 undefined。当变量没有初始化定义的时候就会是undefined

声明了变量但是没有给值

注意事项:

  • 注意一:最好在变量定义的时候进行初始化,而不只是声明一个变量,不然的话就是undefined参与运算 会导致NaN等或者其他的情况;
    • 初始化可以是null, 0 ,false;
  • 注意二:不要显示的将一个变量赋值为undefined
    • 如果变量刚开始什么都没有,我们可以初始化为0、空字符串、
    • 都可以数据类型都可以初始化null
    • null + 1 = 1 number初始化null 不会报错,最好初始化 0
  • 注意三: + 号除了字符串拼接,进行计算的时候,会将两边的运算元隐式转换为number类型

Object 类型是一个特殊的类型,我们通常把它称为引用类型或者复杂类型;

其他的数据类型我们通常称之为 “原始类型或者基本数据类型”,因为它们的值只包含一个单独的内容(字符串、数字或者其他)

Object往往可以表示一组数据,是其他数据的一个集合;

在JavaScript中我们可以使用 花括号{} 的方式来表示一个对象;

Null 类型同样只有一个值,即特殊值 null。

var a=null;

声明了变量a为null值

  • null类型通常用来表示一个对象为空,所以通常我们在给一个对象进行初始化时,会赋值为null;
  • Null存在的意义就是对 对象进行初始化的, 并且在转成Boolean类型时, 会转成false
  • 也是一个对象类型在内存中的地址是 0x0
  • undefined通常只有在一个变量声明但是未初始化时,它的默认值是undefined才会用到;
  • 并且我们不推荐直接给一个变量赋值为undefined,所以很少主动来使用;
  • null值非常常用,当一个变量准备保存一个对象,但是这个对象不确定时,我们可以先赋值为null;
  • 隐式装箱: 当基本数据类型调用方法属性的时候,会创建它的基本包装类型,调用完立即销毁

    1. str被认为是字符串,所以进行String装箱,new String('abc')
    2. 调用Stringsubstring方法。
    3. 销毁这个String对象(拆箱)。
    var str = ‘abc;//string
    str.substring();//string=>String=>String.function=>string
  • 显示装箱

    new String('abc').toString()

注意这里对象类型转换之后为 NaN 空数组为 0,如果数组中元素只有一个并且是可以转换为数字的话转换之后就是相应的数字, 反之的话会被转换为0

  • 转换方式一:隐式转换

    • 使用运算符+或者*乘1

    • +可以将字符转 number

      const str = '1';
      const num = +str;
      const num2 = 1*str
      // 这样也可以
      console.log(+'3')
      console.log(1*'3')
  • 转换方式二:显式转换(强制转换)

    • Number(基础数据类型)
  • 转换方式三:(重要)

    • parseInt(str)

      parseInt() 可以将字符转换成整数类型,

      特点:可以将字符串数字后面的非数字元素自动去除,前提**必须是数字开头的**,否则是NaN 不会四舍五入

      例:120px parseInt()-> 120

    • parseFloat("123.4fsajdflajsflajslf");

      parseFloat() 可以将字符转换成浮点类型,

      特点:可以将字符串数字后面的非数字元素自动去除,前提**必须是数字开头的**,否则是NaN

      例:123.4fsajdflajsflajslf parseInt()-> 123.4

转换后的值
undefinedNaN
null0
true/false1/0
String数字字符串会转成对应的number,非数子字符转为NaN

注意:Null转换的Number等于0

它发生在逻辑运算中,但是也可以通过调用 Boolean(value) 显式地进行转换。

  • 显示转换:Boolean(variable)

  • 隐式转换:

    • 使用 if语句和三元运算符 进行条件判断的时候,会将条件类型隐式转换为boolean类型

    • 使用逻辑 ”非“ 运算符取反之后在取反

      var = message = "Hello" console.log(!!message)

  • 转换规则

    • 直观上为“空”的值(如 0、空字符串、null、undefined 和 NaN)将变为 false。
转化后
0, null, undefined, NaN, ""(5个)false
其他值true
  • 注意

    包含 0 的字符串 “0” 是 true

    一些编程语言(比如 PHP)视 “0” 为 false。但在 JavaScript 中,非空的字符串总是 true。

    • 空对象{}为true,null为false
    • 空数组 [] 也为true
  • 运算符:表示运算方法的特殊字符
  • 运算元:运算元 —— 运算符应用的对象
  • 运算符对应的几个运算元就是几元运算符
运算符运算规则范例
+加法
+链接字符串
-减法
*乘法
/除法
%取余数5 % 2=1
**幂(ES7语法)
在没有 ** 语法的时候
都是使用Math.pow(2,3)
2 ** 3=8(2的3次方),
和**Math.pow(2,3)**相同

= 号也算是运算符,不过多介绍

  • 链式赋值(不推荐可读性太差)
// 链式赋值
var num1 = num2 = num3 = 321
console.log(num1, num2, num3)
运算符运算规则范例结果
=赋值a = 55
+=加后赋值a = 5, a += 27
-=减后赋值a = 5, a -= 23
*=乘后赋值a = 5; a *= 210
/=除后赋值a = 5; a /= 22.5
%=取模 (余数)后赋值a = 5; a %= 21
**=幂后赋值a = 5; a **= 225
  • 自增 ++ 将变量加1;

  • 自减 — 将变量减1

注意:自增自减只能应用于变量

自增自减运算符 在变量前后的区别

Section titled “自增自减运算符 在变量前后的区别”

如果自增/自减的值不会被使用,那么两者形式没有区别;

  • 当我们想要立刻使用自增后的值,那么我们需要使用前置形式;
  • 前置形式返回一个新的值,但后置返回原来的值;
//当自增和自减表达式本身又在其他的表达式中,
var currentIndex = 5
var result1 = 100 + currentIndex++
//result1:105
//表达式运算玩之后:currentIndex:6
var result2 = 100 + ++currentIndex
//106

遇到的时候可以取 mdn 查,到 mdn 搜索标题 运算符优先级

==, != ,> ,< ,>= ,<=

  • == 比较值是否相等,使用抽象相等比较算法比较两个操作数

    在比较不同的基础数据类型的值时,判断运算符 == 两侧运算元先转化为数字类型(Number)在进行比较

    引用类型不会转换 例:Object null,比较的是地址值

    • {} 转换后是 NaN
    • undefined转完之后是 NaN
    • [] 转化之后是0,当只有一个元素 是可以转换为 数值的类型的话,就直接转换为 number
    1. null = undefined

      如果一个操作数是 null,另一个操作数是undefined,则返回true

    2. null 是对象类型不进行比较

      null 转换后也是0 但是他是对象类型比较特殊和原始类型的0相比较返回false,null和null比较是true

    3. 对象比较的是地址值

      如果两个操作数都是对象,则仅当两个操作数都引用同一个对象时才返回true

    4. 运算符的两端,有一个运算元为NaN就为false

      注意NaN == NaN 没有办法比较因为他就不是数值类型,就是为假的 一定要比较使用Object.is, 所以如果任一操作数为NaN,则返回false

    5. 空串和false相等

      空字符串和 false 也是如此,转化后它们都为数字 0;

    • 比较NaN使用Object 或者 isNaN()

      console.log(Object.is(Number(undefined), Number({})));
  • === 严格比较值是否相等

    如果 a 和 b 属于不同的数据类型,那么 a === b 不会做任何的类型转换而立刻返回 false

  • 同样!===也是如此

严格相等的运算符虽然写起来稍微长一些,但是它能够很清楚地显示代码意图,降低你犯错的可能性。

分组操作符()控制的优先级评估表达式

代码块是多行执行代码的集合,通过一个花括号{}放到了一起。

在开发中,一行代码很难完成某一个特定的功能,我们就会将这些代码放到一个代码块中

  • 在JavaScript中,我们可以通过流程控制语句来决定如何执行一个代码块

condition 类型会进行隐式转换成Boolean之后在进行判断

var result = condition ? value1 : value2

  • 补充一:当if语句后面只有一行代码的时候可以省略大括号,

    /*无所谓在同一行*/
    if(flag)console.log("flag")
  • 补充二(重要):if (…) 语句会计算圆括号内的表达式,并将计算结果转换为布尔型(Boolean)。

  • 数字 0、空字符串 “”、null、undefined 和 NaN 都会被转换成 false。

    • 它们被称为“假值(falsy)”;
  • 其他值被转换为 true,所以它们被称为“真值(truthy)”;

switch是分支结构的一种语句:

它是通过判断表达式的结果(或者变量)是否等于case语句的常量,来执行相应的分支体的

与if语句不同的是,switch语句只能做值的相等判断(使用全等运算符 ===),而if语句可以做值的范围判断;

一条case语句结束后,会自动执行下一个case的语句,这种现象为case穿透

case执行完在最后加 break

注意事项:这里的相等是严格相等。

  • 被比较的值必须是相同的类型才能进行匹配。

逻辑运算符 ||(或),&&(与),!(非)

|| && 会产生短路效果也叫(短路逻辑运算符 ) 单个的| & 没有短路效果

短路之后后面的线路都不会执行

  • 可以将多个表达式或者值放到一起来获取到一个最终的结果;

    运算符运算规则范例结果
    &&与:同时为真false&&truefalse
    ||或:一个为真false || truetrue
    !非:取反!falsetrue
    ??(逻辑空赋值运算符)仅在 x 是 (nullundefined) 时对其赋值。

||(或)两个竖线符号表示“或”运算符(也称为短路或)

  • 从左到右依次计算操作数。
  • 处理每一个操作数时,都将其转化为布尔值(Boolean);
  • 如果结果是 true,就停止计算,返回这个操作数的初始值。
  • 如果所有的操作数都被计算过(也就是,转换结果都是 false),则返回最后一个操作数。

重点理解:一个或运算 || 的链会将隐式转换Boolean进行判断,将返回第一个真值停止计算,如果都为假,就返回该链的最后一个的初始值。

注意:返回的值是操作数的初始形式,不会转换为Boolean类型。

同样在if条件判断里也是同样会返回 || 两边运算元的值

//例:
//1、使用比较运算符的情况下返回的是 true||true
if(88<99||77<88)
//2、没有使用比较运算符的情况下 88||77 这样的话返回的是数值要在if里隐式转换成boolean
if(88||77)

用来判断 假 的话给变量赋值,

&&(与)两个竖线符号表示“与”运算符(也称为短路与),因为只要当前项为 false 的时候就不继续判断了

java中单个的 & 不会进行短路,js中 单个的 & 是按位于

  • 从左到右依次计算操作数。
  • 在处理每一个操作数时,都将其转化为布尔值(Boolean);
  • 如果结果是 false,就停止计算,并返回这个操作数的初始值;
  • 如果所有的操作数都被计算过(例如都是真值),则返回最后一个操作数。

重点理解:一个&&的链会将运算元隐式转换为Boolean判断,会返回一个为假的值停止运算,如果全部为真,就返回最后一个初始值。

案例:当 flag = null boolean 隐式转换为假的时候 执行后面的 代码

var s = flag && flag.style.setProperty("color","") //面返回的是undefined

多数用来执行 变量为真的情况下 执行单行代码。

逻辑非运算符接受一个参数,并按如下运算:

  • 步骤一:将操作数转化为布尔类型:true/false

  • 步骤二:返回相反的值;

  • ! 隐式转化 boolean 类型:两个非运算 !! 有时候用来将某个值隐式转化为布尔类型:

第一个非运算将该值转化为布尔类型并取反,第二个非运算再次取反。 最后我们就得到了一个任意值到布尔值的转化。

是一个逻辑运算符,当其 左侧操作数null or undefined 时返回其右侧操作数,否则返回其左侧操作数。

注意:如果左侧操作符也未 null 或者 undefined 的话,会直接返回,左右两边的值都不确定话还时要使用三元运算符

条件循环判断

while 循环的语法如下:

  • 当条件成立时,执行代码块;
  • 当条件不成立时,跳出代码块;

每一次查询都会进行折半查找,减少遍历的次数。

// 二分查找
function binarySearch(arr, key) {
let max = arr.length - 1;
let min = 0;
let currentIndex = 0
let count = 0
//都是要满足min <=max 的条件的的,所以无论min++ 最后大于max 还是max-- 最后小于min都会停止循环
while(min <= max) {
count ++
//防止小数情况,溢出
currentIndex = Math.ceil((max + min) / 2) ;
console.log(currentIndex, min, max, arr[currentIndex])
if(arr[currentIndex] == key ) {
console.log("count", count)
return currentIndex
} else if(arr[currentIndex] < key) {
// 元素小于本身的话 就 + 因为要找到索引
min = currentIndex + 1;
} else if(arr[currentIndex] > key) {
//current 要变 不然死循环 一直找当前索引
max = currentIndex - 1;
}
}
console.log("count", count)
return -1;
}
function foo(arr, key, min = 0, max = arr.length - 1) {
let currentIndex = Math.ceil((max + min) / 2)
console.log(currentIndex, min, max, arr[currentIndex])
if(arr[currentIndex] === key) {
return currentIndex
} else if (arr[currentIndex] < key) {
min = currentIndex + 1
//这里记得要加 return
return foo(arr, key, min, max)
} else if( arr[currentIndex] > key) {
max = currentIndex - 1
return foo(arr, key, min, max)
}
//既不相等 也不大也不小,只有null undefined
return -1
}

do..while的特点是不管条件成不成立,do循环体都会先执行一次;

for循环执行顺序

//第一步:let i=0;
//第二部:i<20;
//第三步;console.log(i)
//最后一步才是 i++
for(let i=0;i<10;i++){
console.log(i)
}
var arr=[123,324,546,7,68,45,9]
//这里是要比较的次数、比较的次数就是 arr.length-1次 例 5个数 比较的次数就是4次
for(var i = 0; i<arr.length-1; i++) {
//比较的就不用再比较了
for(var j = 0; j<arr.length-i-1; j++) {
//升序 同样这里比较的次数也是元素的个数减1
if(arr[j]>arr[j+1]) {
arr[j] = arr[j] + arr[j+1];
arr[j+1] = arr[j] - arr[j+1];
arr[j] = arr[j] - arr[j+1];
}
}
}
console.log(arr.join(","))
// var arr2=arr.sort((a, b) => {
// return a - b
// })

15.4 条件控制break/continue 可以对循环进行控制

Section titled “15.4 条件控制break/continue 可以对循环进行控制”
  • break:推出循环;

  • continue:跳过循环