JavaScript,简称JS,是一种运行在客户端的脚本语言
客户端:浏览器
脚本语言:解释型的计算机高级语言
JS不需要编译,运行过程中由js解释器(引擎)逐行来进行解释并执行
浏览器分成两部分:渲染引擎和JS引擎
JS引擎执行代码时逐行解释每一句JS代码(转换为机器语言),然后由计算机去执行,所以JS归为脚本语言,会逐行解释执行。
JS由ECMAScript、DOM和BOM组成
<input type="button" value="点击" onclick="alert('弹出消息')">
<script>
alert('内嵌式');
script>
<script src="js/my.js">script>
// 单行注释
/*
多行注释
*/
prompt('请输入年龄');
alert('弹出框');
console.log('控制台信息');
内存的模型:
- 栈区:存储比较小的数据,开辟的变量空间,一般都是在栈区开辟。特点,计算机自动开辟空间,速度快,但是小。
- 堆区:一般无法自动开辟空间,都是需要手动开辟,用来存储比较大的数据,特点堆区空间大,但是速度慢。
- 数据区:一般用来存储静态变量以及全局变量
- 代码区:存储二进制程序代码
变量的概念在所有语言当中都有,它的概念是这样的:变量是在程序运行过程中随时可以发生改变的量。但是它的本质,其实是计算机开辟出来的一块空间。我们可以把变量理解为一个容器,这个容器就是来放东西的。
在JS中,如果要拿到一个变量,需要用到关键字var
定义一个变量 var a
给变量当中存储一个值: a=“hello word”
让a当中的值改变 a=“hello js”
最终a里面的输出是"hello js"
当定义一个变量的时候是这样的写法var b=10
;
这种写法被称作初始化,它的本质是和上面的有区别,这句话本质是在开辟空间的同时,往空间里存了一个10;
而上面的写是先开辟空间,空间中并没有值,然后在a=“hello js”这句话之后才存入了值。上面的写法叫赋值。
undefined
数据类型,就有一个值,叫做undefined,是未定义的意思,但是真正的未定义会报错,这个undefined表示的是变量定义了没赋值。number
数字类型,包含小数,整数,进制数,科学计数法等等;它还包含一个特殊的数字类型,叫NaN(not a number);NaN比较特殊,它是当我们期望得到一个数字的时候,但是没有得到一个数字,就会用NaN表示。
定义一个变量存数字,可以存整数,小数,进制数,科学计数法。
在number中还有一个最大值和最小值分别用Number.MAX_VALUE
和Number.MIN_VALUE
来表示。
在number中如果得到的值是一个极限,正无穷infinity 负无穷-infinity表示。
针对特殊的NaN给了一个可以检测数据是否是NaN的方法是isNaN();如果我们需要知道这个数字是不是NaN,就要用到这个方法。
string
字符串,在很多语言中都有字符串类型,字符串一般都有定界符,在JS中定界符是双引号或者单引号。"赵丽颖"
'赵丽颖'
都表示一个字符串。
""
(双引号),''
(单引号)都可以作为定界符,因为在某些时候,字符串中也会出现定界符,这时候交叉使用这两种定界符就会解决歧义。
\在js当中也是转义字符,\n 换行的意思
boolean
布尔类型,只有两个值,要么是true,那么是false;在js中布尔类型严格区分大小写,TRUE和FALSE不是布尔类型,布尔值是小写的true和false;null
类型,这个类型中只有一个值就叫做null。它代表空的意思。它虽然属于基本数据类型,但是null通常用来表示一个空对象。
当我们定义的一个变量,以后需要存储对象的时候,通常用null来对这个变量进行初始化。
null是一个很特殊的值,它代表一个空对象,我们可以认为它代表一个空对象的引用,它求出来的类型是object,但是因为他就一个值,所以把他归为基本数据类型。
一般,当我们需要一个变量存储数字的时候 var num=0
当我们需要一个变量存储字符串的时候 var str=''
当我们需要一个变量存储布尔的时候 var bool=true
当我们需要一个变量存储对象的时候 var obj=null
因为JS中变量是一个弱类型的变量,也叫做松散类型的变量。也就是说这个变量里面存储的值可以是任意类型。这样的话会让我们茫然,我们如果拿到别人返回来的一个数据,将无法知道这个数据是什么类型的数据。
因此JS当中提供了一个关键字typeof()
;这个关键字可以用来求变量、常量或者表达式值得类型。
强制转换数字规则:Number()
null转number,值是0
undefined转number,值是NaN
boolean转number,true被转化为1,false被转化为0
string转number
Number()
转换先看整个字符串是不是一个有效的数字类型字符串,看的是整体。如果这个字符串整体不是一个数字类型的字符串,那么转化为NaN。如果确实是一个有效的数字类型字符串,那么转化为相应的数字。
特殊:有效数字字符串前后的空格可以忽略。但是数字中间的空格不能忽略。
console.log(Number("")); // 0
console.log(Number(" 123 ")) // 123
console.log(Number(" 12 3 ")) // NaN
psrseInt()
、parseFloat()
方法转化字符串为数字这两个方法是专门针对字符串而存在的,用来将字符串转化为数字,符合他们各自的规则。因为Number()在转化数字的时候有点绝,只要这个字符串的整体不是一个有效的数字,就会被转化为NaN。而很多时候,我们需要字符串中的数字部分的,因此就多了这两个方法,可以用来转化字符串,并且,不会看整体。
- parseInt是用来转化整数的
- parseFloat是用来转化小数的
他们两个的转化规则很像。拿到字符串后,不会看整体,从字符串的第一个字符开始,一个一个往后进行判断。如果碰到第一个字符是数字,那么再去判断第二个字符,依次往后,当碰到有效字符不是数字的时候结束。会把字符串转化为前面的数字部分。
parseInt和parseFloat空字符串转化为NaN 字符串中都是空格也转化为NaN
字符串中存在e,e在小数中会识别,在整数中无法识别。也可以用parseFloat和Number识别,但是parseInt不可以识别。
console.log(parseInt(" 12 3")); // 12
console.log(parseInt("a")); // NaN
console.log(parseInt(" ")); // NaN
强制转换bool规则:Boolean()
null转boolean false
undefined转boolean false
string转boolean 非空字符串为真true 空字符串为假false
number转boolean 除了0和NaN为false以外 其他都为true
强制转换字符串规则:String()
null转string
undefined转string
boolean转string
number转string
var a = 10;
console.log(a.toString());
var b = 10;
console.log(String(b));
var c = 10;
console.log(c + '');
表达式是一个整体,表达式是有值的;
在JS当中参与运算的时候,数据类型会发生隐式转换
+ - * / %
1 - * / %
算术运算符,在运算的时候,和数学当中的做法完全一样。只是在运算符左右两边的数据类型不同的时候,会发生自动隐式转换。他们如果不是数字,那么会全部先转化为数字,然后再进行运算。
2 -
还可以作为一元运算符,一元运算符意思是负的意思,作为一元运算符的时候,会把数据转化为数字,但是是负数。
3 +
这个运算符比较特殊,如果两边都是数字,那么按照数字的加法运算去做运算。如果至少有一边不是数字而是字符串,那么是拼接字符串。+
这个运算符也可以作为一元运算符,是正的意思,它可以用来把一个数据转化为数字,正的数字。
4 %
它可以求一个数能否被另一个数整除,它可以求一个数各个位上的数字
任意的一个数对n求余,余数都会落在0~n-1之间
=
作用:把=
右边的值赋值给=
左边的变量,左边一定是变量,右边可以是常量,变量以及表达式,但是右边最终都是把相应的值给了左边;
+= -= *= /= %=
复合赋值运算符
a += b <=====> a = a + b
++ --
作用是让一个变量自增1或者自减1, 这两个运算符只能和变量组成表达式。
a++
++
在后,先赋值(先把a的值赋值给a++
这个表达式整体)再++
(默默滴让a的值自增1)
++a
++
在前,先++
(先让a的值默默滴自增1)再赋值(再把a的值赋值给++a
这个表达式整体)
> < >= <= == != === !==
关系表达式的值都是布尔值
如果关系表达式两边都是数字,那么直接比较
如果关系表达式两边都是字符串,那么比较字符串当中对应字符的Unicode码
如果有一边是数字,另外一边是其它的基本数据类型,那么会先转化为数字,然后进行比较
如果有一边是null或者undefined,并且判断相等和不相等的时候,null和undefined不会被转化为任何数,但是null == undefined。
如果有NaN出现,那么任何值和NaN的比较都是false, NaN和自己比较也是false。(任何值和NaN的四则运算都是NaN)
关系运算符两边同时为字符串,比较特殊,比较的是Unicode码
两边如果出现至少一个null或者undefined,并且比较的是相等和不相等,他们不会转化
除此以外,都会向数字看齐。
=== !==
相等比较的是值,全等比较的是类型和值。
&& || !
逻辑运算符通常用在两个以上的关系表达式之间,组成一个新的逻辑表达式
&&
关系表达式1 && 关系表达式2
一假则假,两个关系表达式必须同时为真,整个逻辑表达式才为真。
||
关系表达式1 || 关系表达式2
一真则真,其中一个为真整个逻辑,表达式就为真。
!
它是一个一元运算符,!(关系表达式或者逻辑表达式)
非真即假,非假即真;
!
要求后面的数据是一个布尔型,所以!
可以间接的去把一个非布尔型数据转化为布尔型的数据,但是是相反的,如果要得到正确的布尔值,等加两个!
。
&& ||
具有短路效果:
表达式1 && 表达式2
如果表达式1的值为假,则以表达式1的值作为整个表达式的值,如果表达式1为真,则以表达式2的值作为整个表达式的值。
表达式1 || 表达式2
如果表达式1的值为假,则以表达式2的值作为整个表达式的值,如果表达式1的值为真,则以表达式1的值作为整个表达式的值。
表达式1,表达式2,表达式3……,表达式n
;
执行过程:从左到右依次执行每个表达式。以最后一个表达式的值作为整个表达式的值。
表达式1?表达式2:表达式3;
执行过程:先执行表达式1,根据表达式1的真假,决定是执行表达式2还是3;
如果表达式1的值为真,那么执行表达式2,如果为假执行表达式3。
最后以执行的那个表达式的值作为整个表达式的值。
var a = 1, b = 2;
var c = (a + b, a - b, a * b, a / b);
console.log(c); // 0.5
var d = a++ + b++;
console.log(d); // 3
逗号运算符优先级最低
=
优先级比逗号高,但是也很低
单目运算符优先级比双目优先级高。
if(表达式){
语句块;
}
先判断()当中的表达式是否为真,如果表达式为真,执行if后面花括号当中的语句块,如果为假,则跳过if语句,执行if语句之下的代码。
if(表达式){
语句块;
}else{
语句块;
}
先判断()当中的表达式是否为真,如果表达式为真,执行if后面花括号当中的语句块,如果为假,则执行else后面花括号当中的语句。
其实第一种和第二种本质是相同的,第一种和第二种都是把一件事情分成了两个分支,一个代表真的情况,一个代表假的情况。
if(表达式){
语句块;
}else if(表达式){
语句块;
}else if(表达式){
语句块;
}else{
语句块;
}
switch分支语句
switch(表达式){
case 值1:
语句块1;
break;
case 值2:
语句块2;
break;
case 值3:
语句块3;
break;
case .......
default:
语句块;
break;
}
===
而不是==
for(表达式1;表达式2;表达式3){
语句块; //循环体
}
表达式1 一般情况是一个初始化表达式
表达式2 一般情况是一个关系表达式
表达式3 一般情况是一个自增自减表达式
执行过程: 先执行表达式1,然后执行表达式2,再执行循环体,最后执行表达式3. 再次循环的时候,和表达式1就不再有关系了。第一次执行完表达式3之后,执行表达式2,再去执行循环体,以后的循环都是如此。
注:只有第一次循环的时候,会去执行表达式1;
while(表达式){
语句块; //循环体
}
while循环其实是for循环的变种,它把for循环当中的第一个表达式和第三个表达式换了位置。
var str = "symon";
for (var a = 0; a < str.length; a++) {
console.log(str[a]);
}
var b = 0;
while (b < str.length) {
console.log(str[b]);
b++;
}
do{
语句块;//循环体
}while(表达式);
注:while循环和do…while循环之间的区别是什么?
do…while循环是根据while循环而来的,它把while循环的循环体,从下面搬到了上面。这样的话,do…while循环,在执行的时候,就会先执行一遍循环体,之后再判断条件。如果条件为真,继续执行循环体,如果条件为假,则退出循环。也就是说,do…while循环,无论条件真假,都会至少执行一次循环体。
而while循环,它会先判断条件,然后根据条件的真假决定是否执行循环体。当条件为真时,执行循环体,当条件为假退出循环。也就是说,while循环,它的条件一开始如果就是假的,那么一次循环体也不会执行。
在JS当中,对象是所有的引用数据类型的基础;
js当中没有类的概念,只有对象。也就是说一切皆对象。我们可以认为JS当中的类也是对象。
Object 对象,是所有对象的基础。
JS当中,对象就是一组无序的名值对的集合;
用来描述一个集合。
这种方式简单粗暴,是我们以后常用的定义对象的方式;
var obj = new Object()
这样创建出来的对象是一个空对象,里面的属性需要自己手动添加。这样的方式不常用。
属性就是我们所说的名值对的名,属性值就是名值对的值;
方法:方法名就是我们的属性名,只不过这个属性的值是一个函数。
访问对象的属性有两种方式:
.
语法:对象.属性
属性可以不加双引号,直接访问。一个特殊,如果属性名是数字,那么点语法失效,这会必须用到
[]
语法。
[]
语法:对象["属性名"]
中括号去访问对象属性的时候,里面的属性名,必须加上双引号,有一个特例,如果属性名是数字,不可以加。
[]
语法比.
语法优越的一点,它可以用变量来替代属性名,但是没人这样干。因此,以后我们常用的是点语法,而很少用到[]
语法。
对象.属性 = 新的值
就是修改对象的属性值
对象.属性 = 属性值
添加属性和修改属性比较相似,添加属性的时候,属性存在就是修改,属性不存在就是添加;
delete 对象.属性
删除对象的属性;
for in 遍历对象,对象的遍历运用for很复杂,通常都是运用for in来遍历。
var symon = {
"name":"symon",
"age":18,
"sex":"男"
};
symon.id = 1;
symon.age = 16;
for(key in symon){
console.log(key+":" + symon[key]);
}
基本数据类型,值会直接存储在栈区的变量当中。
var a = 10;
var b = a;
a = 11;
console.log(b);
也就是说我们在栈区开辟了两个变量空间a和b,在a和b当中都存储了一个10,当a改变为11的时候,他们的空间不是同一个,b中的值还是10;
引用数据类型,变量空间会在栈区开辟,但是值不是直接存储在栈区的,值是在堆区存储的。栈区变量只是存储值的引用(本质是一个地址)。
var a = {};
var b = a;
a.name = "symon";
console.log(b);
我们发现b里面也有name属性,symon。因为a和b都存储了同一个对象的引用,当有一个去对值做改变的时候,另外一个访问的是同一个空间的值,也会发生改变。