JavaScript的实现
- ECMAScript 核心
- DOM 文档对象模型
- BOM 浏览器对象模型
ECMAScript
- 语法
- 类型
- 语句
- 关键字
- 保留字
- 操作符
- 对象
script 标签
- async 可选,表示版本应立即下载,但不妨碍页面中其他的操作
- charset 可选,指定代码的字符集
- defer 可选,表示脚本可以延迟到文档被解析和显示之后再执行
- language 被弃用,用于编写代码的使用的脚本语言
- src 可选,在使用外部文件时必选,表示外部文件的地址
- type 可选,不写默认是text/javascript
script的加载顺序
不存在async
和 defer
的属性,浏览器就会按照script
所在的位置进行解析。
noscript 元素
用以不支持JavaScript
的浏览器显示替代的内容,这个元素可以包含body
中任意一个html
元素 但 <script>
除外。
元素中的内容只有在一下情况才会显示
- 浏览器不支持脚本
- 浏览器支持脚本,但禁用
脚本无效会向用户展示下面的信息,而在启动了脚本的浏览器,用户则不会看到。
<body>
<noscript>
<p>本页面需要浏览器支持(启动)JavaScript</p>
</noscript>
</body>
JavaScript
任何语言的核心都会描述该语言的基本工作原理,而这通常要涉及到这门语言的,语法,操作符,数据类型,内置功能等用于构建复杂的解决方案的基本概念。
语法
JavaScript
中的变量
,函数名
,操作符
都是区分大小
写的,例如变量A
和变量a
是表示2个不同的变量。
**标识符 **
定义变量/函数/形参/属性等应该遵守下面的规则
- 第一个字符必须是字母、下划线( _ )、或者一个美元符号( $ )
- 其他的字符可以是字母、下划线、美元符号或者数字
- 不可以是关键字或者保留字以及true和false、null 作为标识符
建议我们的标识符采用驼峰命名式:myProfile
注释
- 单行注释
//这里是单行注释的代码
- 多行注释
/* 这里是多行注 释的代码 */
严格模式
“use strict”;
这行代码虽然看起来是字符串,而且没有赋值给任何变量。但它是一个编译指示,告诉浏览器引擎切换成严格模式编译代码。
严格模式下,JavaScript 的执行结果会大不相同。
如果在函数内,则表示只是这个函数用严格模式编译。
function fn(){
"use strict";
//函数体
}
语句
每行代码结束都以一个分号( ; )结尾,如果省略分号也不会报错,但不推荐。
关键字和保留字
JavaScript 中还存在多个关键字和保留字。在 JavaScript 中关键字和保留字不能用作标识符。
关键字 -> 可用于表示控制语句的开始或者结束,或者用于执行特定的操作符。
保留字 -> 虽然还没有任何特定的用途,但在将来可能会被用坐关键字。
变量
在 JavaScript
中,变量是松散的,定义的变量其实就是占位符,定义变量可使用 var
和 let
定义。
如果忽略了 var 或者 let 则该变量会升级为 全局变量
var 和 let 区别
var
- 通过 var 定义的变量,作用域是封闭的,是全局的变量
- var 声明的变量会提升到作用域的顶部并初始化为
undefined
- var 声明的变量可以在同一个作用域内重复声明
let
- ES6新加
- 通过 let 定义的变量,只能在当前作用域块内,或者是在父级作用域内
- let 声明的变量会提前声明但不会初始化,在变量前输出会报错
- let 声明的变量不能在同一个作用域内重复声明
例子
在 for 循环里 使用 var 定义 i,变量 i 是作为代码块所在函数的局部变量来声明的,在循环外依旧可以访问 i 的值。但是使用 let 声明变量 i,在循环之后变量 i 将不复存在
for (var i=0;i<10;i++){
console.log(i)
}
i // 10
i++ //10
i // 11
for (let i=0;i<10;i++){
console.log(i)
}
i //报错 ,i is not defined
常量
使用 const 关键字创建,使用方式和 var , let 类似。但 const 声明在一开始赋值之后,就不可以在修改或删除该值了。
const log = "log";
log = "log1"; // 报错
delete log // false
并且在同一个作用域中,常量名称不能和其他变量名称相同。
const log = "log";
var log = "log var"; //报错
快捷定义变量
以下代码表示定义了3个变量
let age = 1,name = "kk",found = false;
严格模式下不可以定义为名 eval
和 arguments
的变量名
数据类型
JavaScript中有2种数据类型,一种是简单数据类型也称为基本数据类型,还有一种复杂类型也称为引用类型
基本数据类型
- String
- Number
- Boolean
- Undefined
- Null
- Symol
复杂数据类型
- Object
- Arrary
- Function
typeof 操作符
typeof 可以检测某个变量的数据类型
typeof "sss" //"string"
typeof 2 //"number"
typeof {} //"object"
typeof null //"object"
typeof function(){} // "function"
...
类型解说
Number
- 过大或过小的数值,可以用e(E)表示法表示,e前面的数值乘以10的指数次幂,e的后面是10的幂中的指数,例如:3.125e2 = 3.125*10²
- 用e表示过小的值,例如0.00000000000000003,可以用简洁的3e-17表示,默认情况下会将小数点后面带6个零以上的浮点数值转换为e表示,例如0.0000003会为转为3e-7,0.00000000003转为3e-11
- 由于浮点数值的最高精确是17位小数,但在进行计算时却远远不如整数,例如0.1+0.2 不等于0.3而是0.30000000000000004。当然0.1+0.2 这是个特殊点
- NaN 特殊的值,NaN与任何值都不相等,包括自己
- NaN与任何值操作都是NaN,除了与字符串
- isNaN,判断是否是一个数值,返回值为true或false。true表示不是一个值,false表示是一个数值
- Number()转换
- boolean 类型转为 0 和 1
- 数字则只会简单传入和返回
- null,返回0
- Undefined,返回null
- 如果是字符串数字,则会转为对应的数字,数字前面有0则会忽略
- 如果是空字符串,则会返回0
- 其他的字符串内容,返回NaN
- 对象类型,则会先调用对象valueof()方法,如果返回NaN,在调用对象toString()方法,返回字符串值
- parseInt() 2个参数
- 第一个检测的字符必须是 - + 0 以及数字,并且会去到后面不是一个数字的值为止,如果没有符合,则返回NaN
- 支持 八进制,十进制和十六进制,如果第二个参数不写默认是十进制
- 如果检测的是浮点数,则小数点后面的不会返回。
- parseFloat() 2个参数
- 和parseInt()一样,不同的是,parseFloat()可以返回小数点后面的浮点数
String
- 由双引号("")和单引号(’’)以及字符串模板(``)(es6新加)组成的。
- 有length属性
- 任何类型任何值与字符串相加,都会变成字符串,但下面的要记下
[]+"a" //"a" []+"3" //"3" []+"aa"+"33" //"aa33" [2,2]+"33" //"2,233" {}+"aa" //NaN {obj:22}+"aa" // NaN {obj:22}+"2" // 2 {obj:22}+"" // 0 {obj:""}+"" //0 [] == 0 //true [] == "" //true [] == {} // false
- 转换值
- toString()方法,因为每个类型都有toString()方法,所以一般使用toString()转为字符串,默认情况下不写参数,但也可根据传递的参数返回二进制,八进制,十进制和十六进制等
- null 和 Undefined 没有toString()方法
- String(),当值有toString()方法时,会返回默认的toString()的值,如果值是null 或者Undefined,则返回字面量"null"或"Undefined"
Boolean
- 该类型只有2个值,即 true 或 false,均为小写
- 在boolean类型中,只有空字符串、0、NaN、null、Undefined为false,其余都是true
Object
Object类型是对象所有实例的基础,也就是说Object上的所有属性和方法,在它的实例中都可以应用。
- 创建方式。2种
let obj = new Object();//不写括号不会报错,但不推荐
let obj2 = {}
object的属性和方法
- constructor: 返回该对象的构造函数对象,对于上面的例子而言,返回的是Object()
- hasOwnProperty(name): 用于检测某个属性是否存在于当前对象实例中。例如:o.hasOwnproperty(“name”)
- propertyIsEnumerable(name): 用于检测某个属性是否能够使用for-in语句进行枚举
- toLocaleString(): 返回对象的字符串表示
- toString(): 返回对象的字符串表示
- valueOf(): 返回对象的原始值
Null
- 该类型也只有一个值,null
- null 表示一个空的指针对象,这也是typoef 判断null 为object的原因
- 因为Undefined 是派生自null 所以 Undefined == null 是true
- 一般来讲,null是用于想要保存对象但还未赋值时。
Undefined
- 该类型只有一个值,即Undefined
- 表示为初始化的值,声明了变量但为初始化的值,但只声明了变量和为未定义变量的还是不一样的。
Symol
操作符
一元操作符
只能操作一个值的操作
- 递增和递减
分别有前置和后置2种类型- 前置是给一个值进行递增或递减 例如:let a = 0; ++a //1
- 后置是不会先累加而是等这个语句结束后再累加,等下次运行才会有更新值
布尔操作符
用于进行一些判断,分别有逻辑非(!)、逻辑与(&&)、逻辑或(||)
- 逻辑非 就是取反,例如 let a = !false; a//true
- 逻辑与 判断的值都必要为true才可以,有一个为false就不会在是true
规则- 如果都是true,则返回后面的值
- 如果第1个是对象,则返回第二个操作数
- 如果第二个是对象,则只有在第1个操作数为true,才会返回
- 都是null,则返回null
- 都是NaN,则返回NaN
- 都是Undefined,则返回Undefined
- 逻辑非 进行判断的值有一个为true就可以,如果第一个判断为true,则不会再往下找
规则- 第一个操作数是对象,则返回第一个
- 第一个为false ,则返回后面的
- 都是true,则返回第一个
- 都是null,则返回null
- 都是NaN,则返回NaN
- 都是Undefined,则返回Undefined
加减乘除操作符
关系操作符
- 大于(>)
- 小于(小于)
- 大于等于(>=)
- 小于等于(<=)
相等操作符
- 相等 ==
- 不等 !=
- 绝对相等 ===
注意- null == undefined //true
- null/undefined == 0/""/false //false
- 双等 和 三等 的区别
- 双等 只要值一样就可以为true,会默认转化值的类型
- 三等,必要要类型和值都一样才可以为true,不会转化类型
条件操作符
- 三元运算符 null == undefined ? “true” : “false”
if 语句
判断语句
if(//判断){
//代码体
}else{
//代码体
}
do while 语句
属于后测试循环语句
至少先执行一次,先执行在做判断。
do{
//代码体
}while(//判断)
while 语句
属于前测试循环语句
先判断在执行。
while(//判断){
// 代码体
}
for 语句
属于前测试循环语句
for(表达式1,表达式2,表达式3){
//代码体4
}
执行过程:
初始循环
表达式1,为初始化值,可以在 for 循环体外设置也可以在 for 内设置
表达式2,为代码执体执行的判断条件,如果表达式1符合表达式2,则执行代码体4,不符合则停止执行,然后执行表达式3。
再次循环
先执行表达式2,判断表达式3是否符合表达式2,符合则执行代码体4(一直重复到表达式3不再符合表达式2),不符合则停止执行,最后执行表达式3。
for in 语句
迭代语句,可以用来枚举对象的属性。
for(let propName in window){
console.log(propName);
}
上面的代码,将会打印 window 对象的所有属性的名称。随着每次执行循环,都会将 window 对象中的一个属性名赋给 propName。
label 语句
label 可以在代码中添加标签。
break 和 continue 语句
break 和 continue 都可以在循环中控制代码的执行。
break:会立即退出循环,并强制继续执行循环后面的语句。
continue:也会立即退出循环,但退出循环后会从循环的顶部继续执行。
with 语句
将代码的作用域设置在一个特定的对象中。从而简化多次对同一个对象的编写。
let qs = location.search.substring(1);
let hostName = location.hostName;
let url = location.href;
with(location){
let qs = search.substring(1);
let hostName = hostName;
let url = href;
}
由于大量使用 with 语句会导致性能下降,同时也会给调试代码造成困难,所以不建议在大型开发项目中使用。
switch 语句
seitch 语句中的值对比,都三等模式(===)。
switch(表达式){
case value:
//代码体
break
case value:
//代码体
break
default:
//代码体
}
case:如果表达式等于value,则执行后面的代码语句,而 break 关键字会跳出 switch 语句。如果省略 break 关键字会导致执行完当前的 case,后面的 case 也会执行。
default:表示当表达式不匹配任何 case 的时,执行此代码。相当 else 语句。
函数
使用 function 关键字来声明,后面跟一组参数(没有则不写)以及函数体。
function fn(name){
//函数体
alert(name)
}
fn("k")// 调用函数
函数在定义时不用指定是否有返回值,函数可以在任何时候通过 return 语句后面的值来实现返回值。
function sum(num1,num2){
return num1 + num2;
console.log("这里不会执行");
}
sum(10,20) // 30
sum 函数返回 2 个参数的加法运算的值,return 语句后面跟着的值会当做是函数的返回值,而 return 语句之后的任何代码都不会在执行。
return 语句也可以不带任何返回值,函数在执行到 return 语句之后停止,然后返回undefined。当然函数中不写 return 语句也是默认返回 undefined。
严格模式对函数的限制
- 函数名和参数不能以 eval 和 arguments 命名
- 不能出现多个参数名相同的情况
参数
ECMAscript 函数不介意传递的参数是多个还是不传,也不在乎传递的是什么类型。
在函数内部有一个 类数组 -> arguments。也就是说,如果函数没有传递参数或者传递了参数都可以用 argument 来获取参数。并且 argument 获取的参数与我们传递的参数值相同,如果我们修改了某个参数的值或者是 arguments 对应的值,都会有所改变。
类数组 -> 可以使用方括号语法访问每个元素,有 length 属性。
没有传递值的参数,就像是自动赋值了 undefined 值。
function fnn(name,age,num){
name = "222";
arguments[1] = "1000"
alert(name);
alert(age);
alert(num)
}
fnn("111",100)
函数名虽然可以被重复定义,但调用函数时,只会执行最后那个函数,前面的都会被覆盖。