doc

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

原文地址:https://www.cnblogs.com/phennry/p/5805036.html