1、简介
ECMAScript
JavaScript语言的标准,被称为ECMAScript标准。最新版ECMAScript 6标准(简称ES6)在2015年6月正式发布。
JavaScript组成
ECMAScript(ES):js核心解释器
DOM (Document Object Model 文档对象模型):操作HTML对象,使用document。
BOM (Browser Object Modal 浏览器对象模型):操作浏览器对象,使用window。
快速入门
<script>...</script>
包含的代码就是JavaScript代码脚本,它将直接被浏览器执行。
<html>
<head>
<script>
alert('Hello, world');
</script>
</head>
<body>
...
</body>
</html>
第二种方法是把JavaScript代码放到一个单独的.js文件,然后在HTML中通过
<script src="..."></script>
引入这个文件。
<html>
<head>
<script src="/static/js/abc.js"></script>
</head>
<body>
...
</body>
</html>
有些时候你会看到 script标签还设置了一个type属性,但这是不必要的,因为默认的type就是JavaScript,所以不必显式地把type指定为JavaScript
<script type="text/javascript">
...
</script>
1.1 基础语法
JavaScript的语法和Java语言类似,每个语句以;结束,语句块用{…}。但是,JavaScript并不强制要求在每个语句的结尾加;,浏览器中负责执行JavaScript代码的引擎会自动在每个语句的结尾补上;。
var name = 'ruby_ruby';
if (name === 'ruby_ruby') {
alert('1');
}else {
alert('2');
} // 注意,== 判断值是否相等,=== 还判断类型
1.2 注释
// 此处的文字会被忽略,但是之后注释掉一行
/* .....此处的文字会被忽略, 不限于一行
...........................
...........................*/
1.3 大小写
请注意,JavaScript严格区分大小写,如果弄错了大小写,程序将报错或者运行不正常。
数据类型和变量
1.4 数据类型(六种,这里先忽略了ES6新增的Symbel)
js中数据类型可以分成两大类:原始类型和引用类型(对象)。
1.4.1 原始类型与引用类型对比
原始类型
原始类型的数据,存储在内存的栈里面
,同时注意,一旦在栈里面设置了值value,那么就不可以再改变。
看下面的🌰:
var a = 20; // a 指针指着20这个value
|————————————————————————|
| a | 20 |
|————————————————————————|
var b = a; // 多了一个b,同时也是指向一个20的value,但是和a的value不是一个,这只是一个单纯的拷贝而已。
|————————————————————————|
| a | 20 |
| b | 20 |
|————————————————————————|
a = 30;// a 指针换了一个value,注意:20这个value不可变
|————————————————————————|
| | 20 |
| b | 20 |
| a | 30 |
|————————————————————————|
从上面的🌰可以看出,原始类型的赋值直接是给变量直接赋值,而且是通过拷贝而来,赋值之后,a和b就完全没关系了,但是20这个value需要进行回收,这就涉及到垃圾回收了。
引用类型
引用类型的数据,存储在内存的堆里面
,同时引用类型拥有自己的属性和方法,这就是根本的不同。引用类型的赋值就不是拷贝了,而是引用。
var a = new Array(); // a 引用了一个数组对象,注意,变量 a 还存在栈里面,不过栈里面存的是对象的地址。
|——————————————————————————————————|
| a | addressA |
|——————————————————————————————————|
var b = a; // 注意,b拷贝回去的是一个地址,最后 堆 里面的值一个都没变,所以a和b没有区别。
|——————————————————————————————————|
| a | addressA |
| b | addressA |
|——————————————————————————————————|
a.name = 'XXXXX'; // 此时更改的是堆,很明显,b.name也是‘XXXXX’
a.name = 'YYYYY'; // b.name 也是‘YYYYY’
要想彻底改变a和b的关系,需要帮a或者b找到新的引用(也就是新的对象地址)。
1.4.2 数据类型
1、Number
JavaScript不区分整数和浮点数,统一用Number表示,都是浮点型。
Number可以直接做四则运算,规则和数学一致。
但是注意:因为浮点数计算会出现精度缺失问题,所以尽可能不用浮点数记性运算
。
同时注意:NaN是number类型
。
四则运算
&& || ! + - * / %
注意:一般定义基础类型的数据的时候,是不会加 new 的,因为这是对象的创建方法。
const s = Number(0);
typeof(s); // number
const t = new Number(0);
typeof(t); // object
console.log('a' || 0); // 'a' 字符会转变成ASCII码进行计算
console.log('a' && 0); // 0
Number方法
s.toString(); // '8'
// 十进制转换成二进制、八进制、十六进制字符串
s.toString(2);
s.toString(8);
s.toString(16);
Math.abs(a) // 绝对值
Math.min(a,b) // 最小值
Math.max(a,b) // 最大值
2、字符串 string
字符串是以单引号’或双引号"括起来的任意文本。
3、布尔值 boolean
布尔值和布尔代数的表示完全一致,一个布尔值只有true、false两种值,要么是true,要么是false,可以直接用true、false表示布尔值。
&& 与 || 或 ! 非
比较运算符
JavaScript在设计时,有两种比较运算符:
第一种是 == 比较,它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果;
第二种是 === 比较,它不会自动转换数据类型,如果数据类型不一致,返回false,如果一致,再比较。
由于JavaScript这个设计缺陷,不要使用 == 比较, 始终坚持使用 === 比较
。
但是NaN是不用进行===判等的,因为NaN不和任何数字相等,甚至它自己,因此需要采用函数进行。
isNaN(NaN) // true
4、null 和 5、undefined
null表示一个“空”的值。
undefined,它表示“未定义”。
6、对象(引用类型)
JavaScript的对象是一组由键-值组成的无序集合,同时也是最为特别的类型,例如:
var person = {
name: 'Bob',
age: 20,
tags: ['js', 'web', 'mobile'],
city: 'Beijing',
hasCar: true,
zipcode: null
};
JavaScript对象的键都是字符串类型,值可以是任意数据类型。
每个键又称为对象的属性。
要获取一个对象的属性,我们用 对象变量.属性名 的方式:
person.name // 'Bob'
person.age // 20
1.5 垃圾回收机制
上面我们提到过,原始变量的value无法更改,当不使用这个内存后,就需要进行垃圾回收,而程序员是无法直接操纵内存的,就需要JS去判断进行垃圾回收。
JS后台有一个垃圾回收器,有着自己的垃圾回收机制:
1.5.1 引用计数
所谓引用计数,便是这块内存被变量或对象引用的次数,举个🌰:
var a = [1,2,3]; // [1,2,3] 这块内存被变量a引用了。
var b = {
f(); // 函数这块内存被对象b引用了
}
有着引用,那么就不可以释放这块内存,当一块内存的引用为0,就说明没有一个可访问对象或变量需要这块内存,就可以释放掉了。
1.5.2 标记清除
当变量进入环境时,例如,在一个函数中声明一个变量,就将这个变量标记为"进入环境",从逻辑上讲,永远不能释放进入环境变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为"离开环境"。
function test(){
var a = 10; //被标记"进入环境"
var b = "hello"; //被标记"进入环境"
}
test(); //执行完毕后之后,a和b又被标记"离开环境",被回收
垃圾回收机制在运行的时候会给存储在内存中的所有变量都加上标记,然后,它会去掉处在环境中的变量及被环境中的变量引用的变量标记(闭包)。而在此之后剩下的带有标记的变量被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后垃圾回收机制到下一个周期运行时,将释放这些变量的内存,回收它们所占用的空间。
1.6 变量
变量在JavaScript中就是用一个变量名表示,变量名是大小写英文、数字、$和_的组合,且不能用数字开头。
声明一个变量用var语句。
var a; // 申明了变量a,此时a的值为undefined
a = 1; // 定义
console.log(a); // 1 打印a
a = '123'
console.log(a); // '123' 打印a
在JavaScript中,使用等号=
对变量进行赋值。可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量,但是要注意只能用var申明一次。
1.6.1 变量声明提升
JS中存在一个变量提升的概念,所谓变量提升,便是你声明了一个变量,那么 JS 防止出错,默认会把声明提升到代码执行的最前面,举个🌰:
x = 7;
console.log(x); // 7
var x; // 此时没有任何问题,var声明会变量提升
但是注意,变量提升只存在于声明,定义就不行,在举个🌰:
console.log(x); // undefined
var x = 7;
原理
变量提升的原理在于JS代码运行分为两部:编译、执行。编译阶段,会将 = 左侧的字符串进行提升,拉到最上方,= 右侧的则会自然顺序安置,所以会有变量提升。
1.7 strict严格模式
JavaScript里,如果一个变量没有通过var声明就被使用,那么该变量就自动被声明为全局变量:
a = 1; // a现在是全局变量
然而当多个文件同时声明a时会造成变量冲突。使用var声明的变量则不是全局变量,它的范围被限制在该变量被声明的函数体内。
ECMA在后续规范中推出了strict模式,在strict模式下运行的JavaScript代码,强制通过var声明变量,未使用var声明变量就使用的,将导致运行错误。
启用strict模式的方法是在JavaScript代码的第一行写上:
'use strict';
1.8 类型的判断
1、typeof
typeof A 是用来判断 A 的类型:
表达式为:typeof A,返回值为类型:Number/string/object等,typeof对于引用对象统一Object处理,因此判断数组、Set、Map根本分辨不出来。
2、instanceof
instanceof 是用来判断 A 是否为 B 的实例,因此主要用来判断 A 的详细类型,可以进行对象的进一步判断。
表达式为:A instanceof B ,返回值为 true / false 。
3、Object.prototype.toString.call
Object.prototype.toString.call
, 调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。
对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。
Object.prototype.toString.call('') ; // [object String]
Object.prototype.toString.call(1) ; // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call([]) ; // [object Array]
本文来源廖雪峰老师教程的笔记,有疑惑可以直接访问廖雪峰老师教程:https://www.liaoxuefeng.com/wiki/1022910821149312/1023022043494624