JavaScript基础
JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码,浏览器可以解释并作出相应的处理。
一、JavaScript的用法
1、JavaScript代码存在形式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<!DOCTYPE html> < html lang = "en" > < head > < meta charset = "UTF-8" > < title >Title</ title > <!--第一种方式--> < script type = "application/javascript" src = "外部JS文件" ></ script > </ head > < body > <!--第二种方式--> < script type = "text/javascript" > // JS代码 </ script > </ body > </ html > |
2、JavaScript代码存放位置
-
HTML的head中;
-
HTML的body代码块的底部(推荐使用)。
由于HTML代码是从上到下执行,如果Head中的js代码耗时严重,就会导致用户长时间无法看到页面,如果放置body代码块底部,那么即使JS代码耗时严重,也不会影响到用户看到页面效果,只是JS实现渲染的效果慢而已。
二、JavaScript输出
JavaScript可以通过不同的方式来输出数据:
-
使用alert()弹出警告框
-
使用document.write()方法将内容写到HTML文档中
-
使用innerHTML写入到HTML元素
-
使用console.log() 写入到浏览器的控制台
三、JavaScript变量
JavaScript中变量的声明是一个非常容易出错的点,局部变量必须以var开头,如果未加var,则默认表示声明的是全局变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<script type= "text/javascript" > //全局变量 name = 'haifeng' ; function func() { //局部变量 var age = 18; //全局变量 gender = "男" ; } </script> |
JavaScript中代码注释:
-
单行: //
-
多行: /* */
四、JavaScript数据类型
JavaScript中数据类型分为原始类型和对象类型:
-
原始类型(数字、字符串、布尔值)
-
对象类型(数组、字典.......)
特别的,数字、布尔值、null、undefined、字符串是不可变。
-
null:JavaScript语言的关键字,它表示一个特殊值,常用来描述"空值";
-
undefined:一个特殊值,表示变量未定义。
1、数字(Number)
JavaScript中不区分整数值和浮点数值,JavaScript中所有数字均用浮点数值来表示。
转换:
-
parseInt(...):将某值转换成数字,不成功则NaN
-
parseFloat(...):将某值转换成浮点数,不成功则NaN
特殊值:
-
NaN:非数字,可使用isNaN(num)来判断
-
Infinity:无穷大,可使用isFinite(num)来判断
更多类型转换,请参考:http://www.w3school.com.cn/js/pro_js_typeconversion.asp
2、字符串(String)
字符串是由字符组成的数组,但在JavaScript中字符串是不可变的;可以访问字符串任意位置的文本,但是JavaScript并未提供修改已知字符串内容的方法。
常见功能:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
obj.length #长度 obj.trim() #移除空白 obj.trimLeft() #移除左侧空白 obj.trimRight) #移除右侧空白 obj.charAt(n) #返回字符串中的第n个字符 obj.concat(value, ...) #拼接 obj.indexOf(substring,start) #子序列位置 obj.lastIndexOf(substring,start) #子序列位置 obj.substring( from , to) #根据索引获取子序列 obj. slice (start, end) #切片 obj.toLowerCase() #大写 obj.toUpperCase() #小写 obj.split(delimiter, limit) #分割 obj.search(regexp) #从头开始匹配,返回匹配成功的第一个位置(g无效) obj.match(regexp) #全局搜索,如果正则中有g表示找到全部,否则只找到第一个。 obj.replace(regexp, replacement) #替换,正则中有g则替换所有,否则只替换第一个匹配项, #$数字:匹配的第n个组内容; #$&:当前匹配的内容; #$`:位于匹配子串左侧的文本; #$':位于匹配子串右侧的文本 #$$:直接量$符号 |
3、布尔值类型(Boolean)
布尔类型仅包含真假,与Python不同的是其首字母小写。true or flase
-
==:比较值相等
-
!= :不等于
-
=== :比较值和类型相等
-
!== :不等于
-
||:逻辑或
-
&& :且
4、数组
JavaScript中的数组类似于Python中的列表。
常用功能:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
obj.length #数组的大小 # obj.push(ele) #尾部追加元素 obj.pop() #尾部获取一个元素 obj.unshift(ele) #头部插入元素 obj.shift() #头部移除元素 obj.splice(start, deleteCount, value, ...) #插入、删除或替换数组的元素 obj.splice(n, 0 ,val) #指定位置插入元素 obj.splice(n, 1 ,val) #指定位置替换元素 obj.splice(n, 1 ) #指定位置删除元素 obj. slice ( ) #切片 obj.reverse( ) #反转 obj.join(sep) #将数组元素连接起来以构建一个字符串 obj.concat(val,..) #连接数组 obj.sort( ) #对数组元素进行排序 |
5、JSON序列化
-
JSON.string(obj):序列化
-
JSON.parse(str):反序列化
五、语句和异常
1、条件语句
JavaScript中支持两个条件语句,分别是:if和switch。
具体用法:
1
2
3
4
5
6
7
|
if (条件){ } else if (条件){ } else { } |
1
2
3
4
5
6
7
8
9
10
|
switch (name){ case '1' : age =123; break ; case '2' : age = 456; breack; default : age = 777; } |
2、循环语句
JavaScript中支持三种循环语句,分别是:
1
2
3
4
5
6
|
var names = [ "jack" , "tony" , "rain" ]; for ( var i=0;i<names.length;i++){ console.log(i); console.log(names[i]); } |
1
2
3
4
5
6
7
|
var names = [ "jakc" , "tony" , "rain" ] for ( var index in names){ console.log(index); console.log(names[index]); } |
1
2
3
4
5
|
while (条件){ //break; //continue; } |
3、异常处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
try { //这段代码从上而下运行,其中任何一个语句抛出异常改代码块就结束运行 } catch (e){ //如果try代码块抛出了异常,catch代码块中的代码就会被执行; //e是一个局部变量,用来指向Error对象或其他抛出的对象。 } finally{ //无论try中代码是否有异常抛出(甚至是try代码块中有return语句),finally代码块中始终会被执行。 } |
提示:主动抛出异常--->throw Error('xxx')
六、函数
1、基本函数
JavaScript中函数基本上可以分为一下三类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<!DOCTYPE html> <html lang= "en" > <head> <meta charset= "UTF-8" > <title>函数</title> </head> <body> <script> // 普通函数 // function func() { // return ture; // } // 匿名函数 // functions(arg){ // return "tony"; // } // setInterval(function () { // alert(123); // },100); // 自执行函数 // (function(arg){ // console.log(arg); // })('123') </script> </body> </html> |
提示:对于JavaScript中函数的参数,实际参数的个数可能小于形式参数的个数,函数内的特殊值arguments中封装了所有实际参数。
2、作用域(★★★)
JavaScript中每个函数都有自己的作用域,当出现函数嵌套时,就出现了作用域链。当内层函数使用变量时,会根据作用域链从内到外一层层的循环,如果不存在,则异常。
提示:所有的作用域在创建函数且未执行时候就已经存在
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
function f2(){ var arg= 111; function f3(){ console.log(arg); //自己这一级没有往上找,直到找到为止 } return f3; } ret = f2(); ret(); //结果为:111 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<script> function f2(){ var arg= [11,22]; function f3(){ console.log(arg); } arg = [44,55]; return f3; } ret = f2(); ret(); </script> //执行结果为[44,55], //结果为对象 |
下面开始引用一下大神的5句话搞定JavaScript作用域:
-
JavaScript中无块级作用域
-
JavaScript采取函数作用域
-
JavaScript的作用域链
-
JavaScript的作用域链执行前已创建
-
声明提前
"JavaScript中无块级作用域"
1
2
3
4
5
6
7
8
9
10
11
12
|
<script> function Main(){ if (1==1){ var name = 'seven' ; } console.log(name); } Main() </script> //执行结果:serven |
补充:标题之所以添加双引号是因为JavaScript6中新引入let关键字,用于指定变量属于块级作用域
JavaScript采取函数作用域
在JavaScript中每个函数作为一个作用域,在外部无法访问内部作用域中的变量。
1
2
3
4
5
6
7
8
9
10
11
12
|
<script> function Main(){ var innerValue = 'seven' ; } Main(); console.log(innerValue); </script> //报错信息:Uncaught ReferenceError: innerValue is not defined |
JavaScript的作用域链
由于JavaScript中的每个函数作为一个作用域,如果出现函数嵌套函数,则就会出现作用域链。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<script> name = 'jack' ; function Func() { var name = "seven" ; function inner() { //var name = 'six'; console.log(name); } inner() } Func() </script> |
如上述代码则出现三个作用域组成的作用域链,如果出现作用域链后,那么寻找变量时候就会出现顺序
当执行console.log(name)时,其寻找顺序为根据作用域链从内到外的优先级寻找,如果内层没有就逐步向上找,直到没找到抛出异常。
JavaScript的作用域链执行前已创建
JavaScript的作用域链在执行之前已经创建,日后再去执行时只需要按照作用域链去寻找即可。
示例一:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<script> name = 'jack' ; function Func() { var name = "seven" ; function inner() { console.log(name); } return inner; } var ret = Func(); ret(); </script> //结果:seven |
上面代码,在函数被调用之前作用域链已经存在,当执行【ret();】时,由于其代指的是inner函数,此函数的作用域链在执行之前已经被定义为:全局作用域-->Func函数作用域-->inner函数作用域,所以,在执行【ret();】时,会根据已经存在的作用域链去寻找变量。
示例二:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<script> name = 'jack' ; function Func() { var name = "seven" ; function inner() { console.log(name); } name = 'eric' ; return inner; } var ret = Func(); ret(); </script> //结果:eric |
示例二和示例一不同的是,在执行【var ret= Func();】时,Func作用域中的name变量的值已经由seven变成了eric,所以之后执行【ret();】时,就只能找到eric了。
示例三:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<script> name = 'jack' ; function Bar() { console.log(name); } function Func() { var name = "seven" ; return Bar; } var ret = Func(); ret(); </script> //结果:jack |
上述代码,在函数被执行之前已经创建了两条作用域链:
-
全局作用域-->Bar函数作用域
-
全局作用域-->Func函数作用域
当执行【ret();】时,ret代指的Bar函数,而Bar函数的作用域链已经存在:全局作用域-->Bar函数作用域,所以,执行时会根据已经存在的作用域链去寻找。
声明提前:
在JavaScript中如果不创建变量直接去使用,则报错:
1
2
3
|
console.log(name); // 报错:Uncaught ReferenceError: xxoo is not defined |
JavaScript中如果创建值而不赋值,则该值为undefined,如:
1
2
3
4
5
|
var name; console.log(name); //输出:undefined |
在函数内如果这么写:
1
2
3
4
5
6
7
8
|
function FOO(){ console.log(name); var name = 'seven' ; } Foo(); //结果输出:undefined |
上述代码,不报错而是输出undefined,其原因是:JavaScript的函数在被执行之前,会将其中的变量全部声明,而不赋值。所以,相当于上述实例中,函数在"预编译"时,已经执行了var name; 所以上述代码输出结果为undefined。
3、闭包
【闭包】是指拥有多个变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
闭包是个函数,而它记住了周围发生了什么,表现为由一个函数体中定义了另一个函数,由于作用域链只能从内向外找,默认外部无法获取函数内部变量。闭包,在外部获取函数内部的变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<script> function f1(){ var n=999; function f2(){ alert(n); } return f2; } var result=f1(); result(); </script> //结果:警告框999 |
4、面向对象
1
2
3
4
5
6
7
8
9
10
11
|
function Foo (name,age) { this .Name = name; this .Age = age; this .Func = function (arg){ return this .Name + arg; } } var obj = new Foo( 'alex' , 18); var ret = obj.Func( "sb" ); console.log(ret); |
提示:
-
Foo充当的构造函数;
-
this代指对象;
-
创建对象时需要使用new。
上述代码中每个对象均保存了一个相同的Func函数,从而浪费内存。使用原型可以解决这个问题:
1
2
3
4
5
6
7
8
9
10
11
12
|
function Foo (name,age) { this .Name = name; this .Age = age; } Foo.prototype = { GetInfo: function (){ return this .Name + this .Age }, Func : function (arg){ return this .Name + arg; } } |
最后附上大神五句话搞定JavaScript作用域地址:
http://www.cnblogs.com/wupeiqi/p/5649402.html