当前位置: 首页 > article >正文

系列学习前端之第 4 章:一文精通 JavaScript

全套学习 HTML+CSS+JavaScript 代码和笔记请下载网盘的资料:

链接: 百度网盘 请输入提取码 提取码: 6666

1、JavaScript 格式

一般放在 html 的 <head> 标签中。type:默认值text/javascript可以不写,不写也是这个值。

<script type="text/javascript">
	alert("HelloWorld")//页面弹窗
	document.write("HelloWorld")//打印在页面
	console.log("HelloWorld")//浏览器的控制台输出(F12查看控制台或者 console)
</script>

2、引入外部 js

<!-- 引入外部js后,无法在该script中添加内容,即使编写了浏览器也会忽略 -->
<script type="text/javascript" src="../js/script.js"></script>

3、注释

注释中的内容不会被执行,但是可以在源代码中查看,要养成良好的编写注释的习惯。

多行注释:/*  xxx  */  

单行注释://

4、区分大小写

JS中严格区分大小写,也就是abc和Abc会被解析器认为是两个不同的东西。

JS中每一条语句以分号(;)结尾,如果不写分号,浏览器会自动添加,但是会消耗一些系统资源。而且有些时候,浏览器会加错分号,所以在开发中分号必须写。JS中会忽略多个空格和换行,所以我们可以利用空格和换行对代码进行格式化。

5、字面量和变量

字面量:字面量实际上就是一些固定的值,比如 1 2 3 4 true false null NaN "hello",字面量都是不可以改变的。由于字面量不是很方便使用,所以在JS中很少直接使用字面量

变量:变量可以用来保存字面量,并且可以保存任意的字面量。一般都是通过变量来使用字面量,而不直接使用字面量,而且也可以通过变量来对字面量进行一个描述。声明变量:使用 var 关键字来声明一个变量,var a = 666;  var b;

6、标识符

在JS中所有的可以自主命名的内容,都可以认为是一个标识符。标识符应该遵守标识符的规范。比如:变量名、函数名、属性名。

第一个字符必须是一个 字母 下划线( _ ) 或一个 美元符号( $ )
其他字符可以是 字母 下划线 美元符号 数字
按照惯例,ECMAScript 标识符采用 驼峰命名法
但是要注意的是JavaScript中的标识符不能是 关键字 保留字

        - 规范:
            1.标识符中可以含有字母、数字、_、$
            2.标识符不能以数字开头
            3.标识符不能是JS中的关键字和保留字
            4.标识符一般采用驼峰命名法
                xxxYyyZzz

7、数据类型

    - JS中一共分成六种数据类型
        - String 字符串
        - Number 数值
        - Boolean 布尔值
        - Null 空值
        - Undefined 未定义
        - Object 对象

typeof运算符:使用 typeof 操作符可以用来检查一个变量的数据类型。
• 使用方式:typeof 数据,例如 typeof 123。
• 返回结果:
– typeof 数值 number
– typeof 字符串 string
– typeof 布尔型 boolean
– typeof undefined undefined
– typeof null object

    - 其中基本数据类型有    
        - String 字符串
            - JS中的字符串需要使用引号引起来双引号或单引号都行
            - 在字符串中使用\作为转义字符
                \'  ==> '
                \"  ==> "
                \n  ==> 换行
                \t  ==> 制表符
                \\  ==> \    
            - 使用 typeof 运算符检查字符串时,会返回"string"    

将其他数值转换为字符串有三种方式: toString() String() 拼串

            
        - Number 数值
            - JS中所有的整数和浮点数都是Number类型
            - 特殊的数字
                Infinity 正无穷
                -Infinity 负无穷
                NaN 非法数字(Not A Number)
            - 其他进制的数字的表示:
                0b 开头表示二进制,但是不是所有的浏览器都支持
                0 开头表示八进制
                0x 开头表示十六进制
            - 使用typeof检查一个Number类型的数据时,会返回"number" (包括NaN 和 Infinity)

有三个函数可以把非数值转换为数值: Number() parseInt() parseFloat()
Number()可以用来转换任意类型的数据,而后两者只能用于转换字符串。

Number表示的数字大小是有限的,范围是:± 1.7976931348623157e+308

如果超过了这个范围,则会返回± Infinity
NaN ,即非数值(Not a Number)是一个特殊的数值,JS中当对数值进行计算时没有结果返回,则返回NaN。

        - Boolean 布尔值
            - 布尔值主要用来进行逻辑判断,布尔值只有两个
            - true 逻辑的真
            - false 逻辑的假
            - 使用typeof检查一个布尔值时,会返回"boolean"    
        
        - Null 空值
            - 空值专门用来表示为空的对象,Null类型的值只有一个
            - null
            - 使用typeof检查一个Null类型的值时会返回"object"

undefined值实际上是由null值衍生出来的,所以如果比较undefined和null是否相等,会返回true

        - Undefined 未定义
            - 如果声明一个变量但是没有为变量赋值此时变量的值就是undefined
            - 该类型的值只有一个 undefined
            - 使用typeof检查一个Undefined类型的值时,会返回"undefined"

           - 需要注意的是typeof对没有初始化和没有声明的变量都会返回undefined

    - 引用数据类型    
        - Object 对象
        
    - 类型转换
        - 类型转换就是指将其他的数据类型,转换为String Number 或 Boolean
        - 转换为String
            - 方式一(强制类型转换):
                - 调用被转换数据的toString()方法
                - 例子:
                    var a = 123;
                    a = a.toString();
                - 注意:这个方法不适用于null和undefined
                    由于这两个类型的数据中没有方法,所以调用toString()时会报错
                    
            - 方式二(强制类型转换):
                - 调用String()函数【与Java体系类似但是不同,在Java中是:String.valueOf(xxx)】
                - 例子:
                    var a = 123;
                    a = String(a);
                - 原理:对于Number Boolean String都会调用他们的toString()方法来将其转换为字符串,
                    对于null值,直接转换为字符串"null"。对于undefined直接转换为字符串"undefined"
                    
            - 方式三(隐式的类型转换): *****
                - 为任意的数据类型 +""
                - 例子:
                    var a = true;
                    a = a + "";
                - 原理:和String()函数一样    
                
        - 转换为Number
            - 方式一(强制类型转换):
                - 调用Number()函数
                - 例子:
                    var s = "123";
                    s = Number(s);
                - 转换的情况:
                    1.字符串 --> 数字
                        - 如果字符串是一个合法的数字,则直接转换为对应的数字
                        - 如果字符串是一个非法的数字,则转换为NaN
                        - 如果是一个空串或纯空格的字符串,则转换为0
                    2.布尔值 --> 数字
                        - true转换为1
                        - false转换为0
                    3.空值 --> 数字
                        - null转换为0
                    4.未定义 --> 数字
                        - undefined 转换为NaN
                        
            - 方式二(强制类型转换):
                - 调用parseInt()或parseFloat()
                - 这两个函数专门用来将一个字符串转换为数字的
                - parseInt()
                    - 可以将一个字符串中的有效的整数位提取出来,并转换为Number
                    - 例子:
                        var a = "123.456px";
                        a = parseInt(a); //123
                    - 如果需要可以在parseInt()中指定一个第二个参数,来指定进制    
                        
                - parseFloat()
                    - 可以将一个字符串中的有效的小数位提取出来,并转换为Number
                    - 例子:
                        var a = "123.456px";
                        a = parseFloat(a); //123.456
                        
            - 方式三(隐式的类型转换):
                - 使用一元的+来进行隐式的类型转换
                - 例子:
                    var a = "123";
                    a = +a;
                    
                - 原理:和Number()函数一样    
                
        - 转换为布尔值
            - 方式一(强制类型转换):
                - 使用Boolean()函数
                - 例子:
                    var s = "false";
                    s = Boolean(s); //true
                - 转换的情况
                    字符串 --> 布尔
                        - 除了空串其余全是true
                        
                    数值 --> 布尔
                        - 除了0和NaN其余的全是true
                        
                    null、undefined ---> 布尔
                        - 都是false
                        
                    对象 ---> 布尔
                        - 都是true
            
            - 方式二(隐式类型转换):    
                - 为任意的数据类型做两次非运算,即可将其转换为布尔值
                - 例子:    
                    var a = "hello";
                    a = !!a; //true
                
                

8、运算符

JS中为我们定义了一套对数据进行运算的运算符。这其中包括:算数运算符、位运算符、关系运算符等。
        - 运算符也称为操作符
        - 通过运算符可以对一个或多个值进行运算或操作
        - typeof运算符
            - 用来检查一个变量的数据类型
            - 语法:typeof 变量,例如: typeof 123
            - 它会返回一个用于描述类型的字符串作为结果
            
        - 算数运算符
            +    对两个值进行加法运算并返回结果
            -      对两个值进行减法运算并返回结果
            *    对两个值进行乘法运算并返回结果
            /    对两个值进行除法运算并返回结果
            %    对两个值进行取余运算并返回结果
            
            - 除了加法以外,对非Number类型的值进行运算时,都会先转换为Number然后在做运算。
            - 而做加法运算时,如果是两个字符串进行相加,则会做拼串操作,将两个字符连接为一个字符串。
            - 任何值和字符串做加法,都会先转换为字符串,然后再拼串

        - 一元运算符
            - 一元运算符只需要一个操作数
            - 一元的+
                - 就是正号,不会对值产生任何影响,但是可以将一个非数字转换为数字
                - 例子:
                    var a = true;
                    a = +a;
                
            - 一元的-
                - 就是负号,可以对一个数字进行符号位取反
                - 例子:
                    var a = 10;
                    a = -a;
                    
            - 自增
                - 自增可以使变量在原值的基础上自增1
                - 自增使用 ++
                - 自增可以使用 前++(++a)后++(a++)
                - 无论是++a 还是 a++都会立即使原变量自增1
                    不同的是++a和a++的值是不同的,
                        ++a的值是变量的新值(自增后的值)
                        a++的值是变量的原值(自增前的值)

            - 自减    
                - 自减可以使变量在原值的基础上自减1
                - 自减使用 --
                - 自减可以使用 前--(--a)后--(a--)
                - 无论是--a 还是 a--都会立即使原变量自减1
                    不同的是--a和a--的值是不同的,
                        --a的值是变量的新值(自减后的值)
                        a--的值是变量的原值(自减前的值)

逻辑运算符主要有三个:非、与、或
        !
            - 非运算可以对一个布尔值进行取反,true变false false变true
            - 当对非布尔值使用!时,会先将其转换为布尔值然后再取反
            - 我们可以利用!来将其他的数据类型转换为布尔值
        
        &&
            - &&可以对符号两侧的值进行与运算
            - 只有两端的值都为true时,才会返回true。只要有一个false就会返回false。
            - 与是一个短路的与,如果第一个值是false,则不再检查第二个值
            - 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值
            - 规则:
                    1.如果第一个值为false,则返回第一个值
                    2.如果第一个值为true,则返回第二个值
        
        ||
            - ||可以对符号两侧的值进行或运算
            - 只有两端都是false时,才会返回false。只要有一个true,就会返回true。
            - 或是一个短路的或,如果第一个值是true,则不再检查第二个值
            - 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值
            - 规则:    
                    1.如果第一个值为true,则返回第一个值
                    2.如果第一个值为false,则返回第二个值


赋值运算符
        = 
            可以将符号右侧的值赋值给左侧变量
            
        +=
            a += 5 相当于 a = a+5
            var str = "hello";  str += "world";
            
        -=
            a -= 5  相当于 a = a-5
            
        *=
           a *= 5 相当于 a = a*5
            
        /=
            a /= 5 相当于 a = a/5    
    
        %=
            a %= 5 相当于 a = a%5    
            
            
    关系运算符
        - 关系运算符用来比较两个值之间的大小关系的
            >
            >=
            <
            <=
        - 关系运算符的规则和数学中一致,用来比较两个值之间的关系,
            如果关系成立则返回true,关系不成立则返回false。
        - 如果比较的两个值是非数值,会将其转换为Number然后再比较。
        - 如果比较的两个值都是字符串,此时会比较字符串的Unicode编码,而不会转换为Number。

    相等运算符
        ==
            - 相等,判断左右两个值是否相等,如果相等返回true,如果不等返回false
            - 相等会自动对两个值进行类型转换,如果对不同的类型进行比较,会将其转换为相同的类型然后再比较,转换后相等它也会返回true


        !=
            - 不等,判断左右两个值是否不等,如果不等则返回true,如果相等则返回false
            - 不等也会做自动的类型转换。
            
        ===
            - 全等,判断左右两个值是否全等,它和相等类似,只不过它不会进行自动的类型转换,
                如果两个值的类型不同,则直接返回false。也就是会判断 typeof 对应的类型是否相同。
           也就是说”55”==55会返回true,而”55”===55会返回 false;

     
        !==
            - 不全等,和不等类似,但是它不会进行自动的类型转换,如果两个值的类型不同,它会直接返回true。

也就是说 ”55”!=55 会返回false,而 ”55”!==55 会返回 true;

            
        特殊的值:
            - null和undefined
                - 由于undefined衍生自null,所以null == undefined 会返回true。
                    但是 null === undefined 会返回false。
                    
            - NaN
                - NaN不与任何值相等,包括它自身 NaN == NaN //false
                
            - 判断一个值是否是NaN
                - 使用isNaN()函数
                
    三元运算符:
        ?:
            - 语法:条件表达式?语句1:语句2;
            - 执行流程:
                先对条件表达式求值判断,
                    如果判断结果为true,则执行语句1,并返回执行结果
                    如果判断结果为false,则执行语句2,并返回执行结果
                    
    优先级:
        - 和数学中一样,JS中的运算符也是具有优先级的,
            比如 先乘除 后加减 先与 后或
        - 具体的优先级可以参考优先级的表格,在表格中越靠上的优先级越高,
            优先级越高的越优先计算,优先级相同的,从左往右计算。
        - 优先级不需要记忆,如果遇到拿不准的,使用()来改变优先级。

9、流程控制语句

    - 程序都是自上向下的顺序执行的,
        通过流程控制语句可以改变程序执行的顺序,或者反复的执行某一段的程序。
    - 分类:
        1.条件判断语句
        2.条件分支语句
        3.循环语句
        
    条件判断语句
        - 条件判断语句也称为if语句
        - 语法一:
            if(条件表达式){
                语句...
            }
            
            - 执行流程:
                if语句执行时,会先对条件表达式进行求值判断,
                    如果值为true,则执行if后的语句
                    如果值为false,则不执行
        
        - 语法二:
            if(条件表达式){
                语句...
            }else{
                语句...
            }
            
            - 执行流程:
                if...else语句执行时,会对条件表达式进行求值判断,
                    如果值为true,则执行if后的语句
                    如果值为false,则执行else后的语句
            
        - 语法三:
            if(条件表达式){
                语句...
            }else if(条件表达式){
                语句...
            }else if(条件表达式){
                语句...
            }else if(条件表达式){
                语句...
            }else{
                语句...
            }
            
            - 执行流程
                - if...else if...else语句执行时,会自上至下依次对条件表达式进行求值判断,
                    如果判断结果为true,则执行当前if后的语句,执行完成后语句结束。
                    如果判断结果为false,则继续向下判断,直到找到为true的为止。
                    如果所有的条件表达式都是false,则执行else后的语句

条件分支语句
    - switch语句
    - 语法:
        switch(条件表达式){
            case 表达式:
                语句...
                break;
            case 表达式:
                语句...
                break;
            case 表达式:
                语句...
                break;
            default:
                语句...
                break;
        }
        
    - 执行流程:
        - switch...case...语句在执行时,会依次将case后的表达式的值和switch后的表达式的值进行全等比较,
            如果比较结果为false,则继续向下比较。如果比较结果为true,则从当前case处开始向下执行代码。
            如果所有的case判断结果都为false,则从default处开始执行代码。

循环语句

    - 通过循环语句可以反复执行某些语句多次
    - while循环
        - 语法:
            while(条件表达式){
                语句...
            }
            
        - 执行流程:
            while语句在执行时,会先对条件表达式进行求值判断,
                如果判断结果为false,则终止循环
                如果判断结果为true,则执行循环体
                循环体执行完毕,继续对条件表达式进行求值判断,依此类推
                
    - do...while循环
        - 语法:
            do{
                语句...
            }while(条件表达式)
            
        - 执行流程
            do...while在执行时,会先执行do后的循环体,然后在对条件表达式进行判断,
                如果判断判断结果为false,则终止循环。
                如果判断结果为true,则继续执行循环体,依此类推
                
        - 和while的区别:
            while:先判断后执行
            do...while: 先执行后判断
            - do...while可以确保循环体至少执行一次。
            
            
    - for循环
        - 语法:
            for(①初始化表达式 ; ②条件表达式 ; ④更新表达式){
                ③语句...
            }
        - 执行流程:
            首先执行①初始化表达式,初始化一个变量,
            然后对②条件表达式进行求值判断,如果为false则终止循环
            如果判断结果为true,则执行③循环体
            循环体执行完毕,执行④更新表达式,对变量进行更新。
            更新表达式执行完毕重复②
            
    - 死循环
        while(true){
        
        }
        
        for(;;){
        
        }
        

break和continue

• break 和 continue 语句用于在循环中精确地控制代码的执行。
• 使用break语句会使程序立刻退出最近的循环,强制执行循环后边的语句。
• break和continue语句只在循环和switch语句中使用。
• 使用continue语句会使程序跳过当次循环,继续执行下一次循环,并不会结束整个循环。
• continue只能在循环中使用,不能出现在其他的结构中

label

• 使用 label 语句可以在代码中添加标签,以便将来使用。
• 语法:
– label: statement
• 例子:
start: for (var i=0; i < count; i++) {
alert(i);
}
• 这个例子中定义的 start 标签可以在将来由 break 或 continue 语句引用。加标签的语句一般都要与 for 语句等循环语句配合使用。

10、Object 对象

1.对象(Object)
    - 对象是JS中的引用数据类型
    - 对象是一种复合数据类型,在对象中可以保存多个不同数据类型的属性

     - 对象也可以看做是属性的无序集合,每个属性都是一个名/值对。
    - 使用typeof检查一个对象时,会返回object
    - 创建对象
        - 方式一:
             var person = new Object();
                person.name = "孙悟空";
                person.age = 500;
        

- 方式二:
             var person = {
                name:"孙悟空",
                age:500
                };
            
    - 向对象中添加属性
        - 语法:
            对象.属性名 = 属性值;
            对象["属性名"] = 属性值;
            
            - 对象的属性名没有任何要求,不需要遵守标识符的规范,
                但是在开发中,尽量按照标识符的要求去写。
            - 属性值也可以任意的数据类型。

    - 读取对象中的属性
        - 语法:
            对象.属性名
            对象["属性名"]
        - 如果读取一个对象中没有的属性,它不会报错,而是返回一个undefined
        
    - 删除对象中的属性
        - 语法:
            delete 对象.属性名
            delete 对象["属性名"]
            
    - 使用in检查对象中是否含有指定属性
        - 语法:"属性名" in 对象
            - 如果在对象中含有该属性,则返回true
                如果没有则返回false
                
    - 使用对象字面量,在创建对象时直接向对象中添加属性
        语法:
            var obj = {
                            属性名:属性值,
                            属性名:属性值,
                            属性名:属性值,
                            属性名:属性值
                    }
                    
    - 基本数据类型和引用数据类型
        - 基本数据类型(5种)
            String Number Boolean Null Undefined

• 基本数据类型的值是无法修改的,是不可变的。
• 基本数据类型的比较是值的比较,也就是只要两个变量的值相等,我们就认为这两个变量相等。


        - 引用数据类型
            Object
        - 基本数据类型的数据,变量是直接保存的它的值。
            变量与变量之间是互相独立的,修改一个变量不会影响其他的变量。
        - 引用数据类型的数据,变量是保存的对象的引用(内存地址)。
            如果多个变量指向的是同一个对象,此时修改一个变量的属性,会影响其他的变量。
        - 比较两个变量时,对于基本数据类型,比较的就是值,
            对于引用数据类型比较的是地址,地址相同才相同

• 引用类型的值是保存在内存中的对象。
• 当一个变量是一个对象时,实际上变量中保存的并不是对象本身,而是对象的引用。
• 当从一个变量向另一个变量复制引用类型的值时,会将对象的引用复制到变量中,并不是创建一个新的对象。
• 这时,两个变量指向的是同一个对象。因此,改变其中一个变量会影响另一个。

11、栈和堆

• JavaScript在运行时数据是保存到栈内存和堆内存当中的。
• 简单来说栈内存用来保存变量和基本类型。堆内存用来保存对象。
• 我们在声明一个变量时实际上就是在栈内存中创建了一个空间用来保存变量。
• 如果是基本类型则在栈内存中直接保存,
• 如果是引用类型则会在堆内存中保存,变量中保存的实际上对象在堆内存中的地址。

12、数组

    - 数组也是一个对象,是一个用来存储数据的对象
        和Object类似,但是它的存储效率比普通对象要高
    - 数组中保存的内容我们称为元素    
    - 数组使用索引(index)来操作元素
    - 索引指由0开始的整数
    - 数组的操作:
        - 创建数组
             var arr = new Array();
             var arr = [];
            
        - 向数组中添加元素
            - 语法;
                数组对象[索引] = 值;
                arr[0] = 123;
                arr[1] = "hello";
                
        - 创建数组时直接添加元素
            - 语法:
                var arr = [元素1,元素2....元素N];
                - 例子:
                    var arr = [123,"hello",true,null];
                    
        - 获取和修改数组的长度
            - 使用length属性来操作数组的长度
            - 获取长度:
                数组.length
                - length获取到的是数组的最大索引+1
                - 对于连续的数组,length获取到的就是数组中元素的个数
            - 修改数组的长度
                数组.length = 新长度
                    - 如果修改后的length大于原长度,则多出的部分会空出来
                    - 如果修改后的length小于原长度,则原数组中多出的元素会被删除
            - 向数组的最后添加元素
                数组[数组.length] = 值;
                
    - 数组的方法
        - push()
            - 用来向数组的末尾添加一个或多个元素,并返回数组新的长度
            - 语法:数组.push(元素1,元素2,元素N)
        - pop()
            - 用来删除数组的最后一个元素,并返回被删除的元素
        - unshift()
            - 向数组的前边添加一个或多个元素,并返回数组的新的长度
        - shift()
            - 删除数组的前边的一个元素,并返回被删除的元素
        - slice()
            - 可以从一个数组中截取指定的元素
            - 该方法不会影响原数组,而是将截取到的内容封装为一个新的数组并返回
            - 参数:
                1.截取开始位置的索引(包括开始位置)
                2.截取结束位置的索引(不包括结束位置)
                    - 第二个参数可以省略不写,如果不写则一直截取到最后
                - 参数可以传递一个负值,如果是负值,则从后往前数
        - splice()
            - 可以用来删除数组中指定元素,并使用新的元素替换
                该方法会将删除的元素封装到新数组中返回
            - 参数:
                1.删除开始位置的索引
                2.删除的个数
                3.三个以后,都是替换的元素,这些元素将会插入到开始位置索引的前边
                
    - 遍历数组
        - 遍历数组就是将数组中元素都获取到
        - 一般情况我们都是使用for循环来遍历数组:
            for(var i=0 ; i<数组.length ; i++){
                //数组[i]
            }
            
        - 使用forEach()方法来遍历数组(不兼容IE8)
        
            数组.forEach(function(value , index , obj){
            
            });
            
            forEach()方法需要一个回调函数作为参数,
                数组中有几个元素,回调函数就会被调用几次,
                每次调用时,都会将遍历到的信息以实参的形式传递进来,
                我们可以定义形参来获取这些信息。
                value:正在遍历的元素
                index:正在遍历元素的索引
                obj:被遍历对象

数组方法
    reverse()
        - 可以用来反转一个数组,它会对原数组产生影响
    concat()
        - 可以连接两个或多个数组,它不会影响原数组,而是新数组作为返回值返回
    join()
        - 可以将一个数组转换为一个字符串
        - 参数:
            需要一个字符串作为参数,这个字符串将会作为连接符来连接数组中的元素
            如果不指定连接符则默认使用,
    sort()
        - 可以对一个数组中的内容进行排序,默认是按照Unicode编码进行排序
            调用以后,会直接修改原数组。
        - 可以自己指定排序的规则,需要一个回调函数作为参数:
            function(a,b){
                
                //升序排列
                //return a-b;
                
                //降序排列
                return b-a;
            }

13、函数

• 函数是由一连串的子程序(语句的集合)所组成的,可以被外部程序调用。向函数传递参数之后,函数可以返回一定的值。
• 通常情况下,JavaScript 代码是自上而下执行的,不过函数体内部的代码则不是这样。如果只是对函数进行了声明,其中的代码并不会执行。只有在调用函数时才会执行函数体内部的代码。
• 这里要注意的是JavaScript中的函数也是一个对象。也具有普通对象的功能。

    - 函数中可以封装一些代码,在需要的时候可以去调用函数来执行这些代码
    - 使用typeof检查一个函数时会返回function
    - 创建函数
        - 函数声明
            function 函数名([形参1,形参2...形参N]){
                语句...
            }
        
        - 函数表达式
            var 函数名 = function([形参1,形参2...形参N]){
                语句...
            };
            
    - 调用函数
        - 语法:函数对象([实参1,实参2...实参N]);
            fun() sum() alert() Number() parseInt()
        - 当我们调用函数时,函数中封装的代码会按照编写的顺序执行

    - 形参和实参
        - 形参:形式参数
            - 定义函数时,可以在()中定义一个或多个形参,形参之间使用,隔开
                定义形参就相当于在函数内声明了对应的变量但是并不赋值,
                形参会在调用时才赋值。
                
        - 实参:实际参数
            - 调用函数时,可以在()传递实参,传递的实参会赋值给对应的形参,
                调用函数时JS解析器不会检查实参的类型和个数,可以传递任意数据类型的值。
                如果实参的数量大于形参,多余实参将不会赋值,
                如果实参的数量小于形参,则没有对应实参的形参将会赋值undefined

13.1 函数的声明(一)


• 首先明确一点函数也是一个对象,所以函数也是在堆内存中保存的。
• 函数声明比较特殊,需要使用function关键字声明。
var sum = function(a,b){return a+b};
• 上边的例子就是创建了一个函数对象,并将函数对象赋值给了sum这个变量。其中()中的内容表示执行函数时需要的参数,{}中的内容表示函数的主体。

13.2 函数的声明(二)


• 可以通过函数声明语句来定义一个函数。函数声明语句以关键字function 开始,其后跟有函数名、参数列表和函数体。其语法如下所示:
function 函数名(参数,参数,参数...){
函数体
}
• 例如:
function sum(a,b){
return a+b;
}
– 上边我们定义了一个函数名为sum,两个参数a和b。函数声明时设置的参数称为形参(形式参数),这个函数对两个参数做了加法运算并将结果返回。

13.3 函数的调用


• 调用函数时,传递给函数的参数称为实参(实际参数)。
• 如果想调用我们上边定义的sum函数,可以这样写:
var result = sum(123,456);
– 这样表示调用sum这个函数,并将123和456作为实参传递给函数,函数中会将两个参数求和并赋值给result。

传递参数
• JS中的所有的参数传递都是按值传递的。也就是说把函数外部的值赋值给函数内部的参数,就和把值从一个变量赋值给另一个变量是一样的

13.4 返回值

    - 返回值,就是函数执行的结果。
        - 使用 return 来设置函数的返回值。
        - 语法:return 值;
            - 该值就会成为函数的返回值,可以通过一个变量来接收返回值
        - return后边的代码都不会执行,一旦执行到return语句时,函数将会立刻退出。
        - return后可以跟任意类型的值,可以是基本数据类型,也可以是一个对象。
        - 如果return后不跟值,或者是不写return则函数默认返回undefined。
        - break、continue和return
            - break
                - 退出循环
            - continue
                - 跳过当次循环
            - return
                - 退出函数
                
    - 参数,函数的实参也可以是任意的数据类型。

    - 方法(method)
        - 可以将一个函数设置为一个对象的属性,
            当一个对象的属性是一个函数时,
                我们称这个函数是该对象的方法。
        - 对象.方法名();
        - 函数名();    

13.5 执行环境


• 执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。
• 每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。
• 全局执行环境是最外围的一个执行环境。在 Web 浏览器中,全局执行环境被认为是 window 对象,因此所有全局变量和函数都是作为window 对象的属性和方法创建的。
• 某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁。
• 在内部环境可以读取外部环境的变量,反之则不行。

13.6 作用域


    - 作用域简单来说就是一个变量的作用范围。
    - 在JS中作用域分成两种:
        1.全局作用域
            - 直接在script标签中编写的代码都运行在全局作用域中
            - 全局作用域在打开页面时创建,在页面关闭时销毁。
            - 全局作用域中有一个全局对象window,window对象由浏览器提供,
                可以在页面中直接使用,它代表的是整个的浏览器的窗口。
            - 在全局作用域中创建的变量都会作为window对象的属性保存
                在全局作用域中创建的函数都会作为window对象的方法保存
            - 在全局作用域中创建的变量和函数可以在页面的任意位置访问。
                在函数作用域中也可以访问到全局作用域的变量。
            - 尽量不要在全局中创建变量    
        
        2.函数作用域
            - 函数作用域是函数执行时创建的作用域,每次调用函数都会创建一个新的函数作用域。
            - 函数作用域在函数执行时创建,在函数执行结束时销毁。
            - 在函数作用域中创建的变量,不能在全局中访问。
            - 当在函数作用域中使用一个变量时,它会先在自身作用域中寻找,
                如果找到了则直接使用,如果没有找到则到上一级作用域中寻找,
                    如果找到了则使用,找不到则继续向上找,一直会
                    
        - 变量的声明提前
            - 在全局作用域中,使用var关键字声明的变量会在所有的代码执行之前被声明,但是不会赋值。
                所以我们可以在变量声明前使用变量。但是不使用var关键字声明的变量不会被声明提前。
            - 在函数作用域中,也具有该特性,使用var关键字声明的变量会在函数所有的代码执行前被声明,
                如果没有使用var关键字声明变量,则变量会变成全局变量
                
        - 函数的声明提前
            - 在全局作用域中,使用函数声明创建的函数(function fun(){}),会在所有的代码执行之前被创建,
                也就是我们可以在函数声明前去调用函数,但是使用函数表达式(var fun = function(){})创建的函数没有该特性
            - 在函数作用域中,使用函数声明创建的函数,会在所有的函数中的代码执行之前就被创建好了。

13.7 函数内部属性


• 在函数内部,有两个特殊的对象:
– arguments
• 该对象实际上是一个数组,用于保存函数的参数。
• 同时该对象还有一个属性callee来表示当前函数。
– this 
• this 引用的是一个对象。对于最外层代码与函数内部的情况,其引用目标是不同的。
• 此外,即使在函数内部,根据函数调用方式的不同,引用对象也会有所不同。需要注意的是,this 引用会根据代码的上下文语境自动改变其引用对象。

13.8 this 引用的规则


• 在最外层代码中,this 引用的是全局对象。
• 在函数内,this 根据函数调用方式的不同而有所不同:

this(上下文对象)    
    - 我们每次调用函数时,解析器都会将一个上下文对象作为隐含的参数传递进函数。
        使用this来引用上下文对象,根据函数的调用形式不同,this的值也不同。
    - this的不同的情况:
        1.以函数的形式调用时,this是window
        2.以方法的形式调用时,this就是调用方法的对象
        3.以构造函数的形式调用时,this就是新创建的对象

13.9 构造函数

构造函数
• 构造函数是用于生成对象的函数,像之前调用的Object()就是一个构造函数。
• 创建一个构造函数:
function MyClass(x,y) {
this.x = x;
this.y = y;
}
• 调用构造函数:
– 构造函数本身和普通的函数声明形式相同。
– 构造函数通过 new 关键字来调用,new 关键字会新创建一个对象并返回。
– 通过 new关键字调用的构造函数内的 this 引用引用了(被新生成的)对象。

    - 构造函数是专门用来创建对象的函数
    - 一个构造函数我们也可以称为一个类
    - 通过一个构造函数创建的对象,我们称该对象时这个构造函数的实例
    - 通过同一个构造函数创建的对象,我们称为一类对象
    - 构造函数就是一个普通的函数,只是他的调用方式不同,
        如果直接调用,它就是一个普通函数
        如果使用new来调用,则它就是一个构造函数
        
    - 例子:
        function Person(){
        
        }
        
    - 构造函数的执行流程:
        1.创建一个新的对象
        2.将新的对象作为函数的上下文对象(this)
        3.执行函数中的代码
        4.将新建的对象返回
        
    - instanceof 用来检查一个对象是否是一个类的实例
        - 语法:对象 instanceof 构造函数
            - 如果该对象时构造函数的实例,则返回true,否则返回false
            - Object是所有对象的祖先,所以任何对象和Object做instanceof都会返回true
            
    - 枚举对象中的属性
        for...in
        语法:
            for(var 属性名 in 对象){
            
            }
            
        for...in语句的循环体会执行多次,对象中有几个属性就会执行几次,
            每次讲一个属性名赋值给我们定义的变量,我们可以通过它来获取对象中的属性

13.10 new关键字

• 使用new关键字执行一个构造函数时:
– 首先,会先创建一个空的对象。
– 然后,会执行相应的构造函数。构造函数中的this将会引用这个新对象。
– 最后,将对象作为执行结果返回。
• 构造函数总是由new关键字调用。
• 构造函数和普通函数的区别就在于调用方式的不同。
• 任何函数都可以通过new来调用,所以函数都可以是构造函数。
• 在开发中,通常会区分用于执行的函数和构造函数。
• 构造函数的首字母要大写。

13.11 属性的访问

• 在对象中保存的数据或者说是变量,我们称为是一个对象的属性。
• 读取对象的属性有两种方式:
– 对象.属性名
– 对象['属性名']
• 修改属性值也很简单:
– 对象.属性名 = 属性值
• 删除属性
– delete 对象.属性名
• constructor
– 每个对象中都有一个constructor属性,它引用了当前对象的构造函数。

13.12 原型(prototype)


    - 创建一个函数以后,解析器都会默认在函数中添加一个数prototype
        prototype属性指向的是一个对象,这个对象我们称为原型对象。
    - 当函数作为构造函数使用,它所创建的对象中都会有一个隐含的属性执行该原型对象。
        这个隐含的属性可以通过对象.__proto__来访问。
    - 原型对象就相当于一个公共的区域,凡是通过同一个构造函数创建的对象他们通常都可以访问到相同的原型对象。
        我们可以将对象中共有的属性和方法统一添加到原型对象中,
            这样我们只需要添加一次,就可以使所有的对象都可以使用。
    - 当我们去访问对象的一个属性或调用对象的一个方法时,它会先自身中寻找,
        如果在自身中找到了,则直接使用。
        如果没有找到,则去原型对象中寻找,如果找到了则使用,
        如果没有找到,则去原型的原型中寻找,依此类推。直到找到Object的原型为止,Object的原型的原型为null,
        如果依然没有找到则返回undefined
    - hasOwnProperty()
        - 这个方法可以用来检查对象自身中是否含有某个属性
        - 语法:对象.hasOwnProperty("属性名")

14、垃圾回收

• 不再使用的对象的内存将会自动回收,这种功能称作垃圾回收。
• 所谓不再使用的对象,指的是没有被任何一个属性(变量)引用的对象。
• 垃圾回收的目的是,使开发者不必为对象的生命周期管理花费太多精力。

15、原型

15.1 原型继承


• JS是一门面向对象的语言,而且它还是一个基于原型的面向对象的语言。
• 所谓的原型实际上指的是,在构造函数中存在着一个名为原型的(prototype)对象,这个对象中保存着一些属性,凡是通过该构造函数创建的对象都可以访问存在于原型中的属性。
• 最典型的原型中的属性就是toString()函数,实际上我们的对象中并没有定义这个函数,但是却可以调用,那是因为这个函数存在于Object对应的原型中。

15.2 设置原型

• 原型就是一个对象,和其他对象没有任何区别,可以通过构造函数来获取原型对象。
– 构造函数. prototype
• 和其他对象一样我们可以添加修改删除原型中的属性,也可以修改原型对象的引用。
• 需要注意的是prototype属性只存在于函数对象中,其他对象是没有prototype属性的。
• 每一个对象都有原型,包括原型对象也有原型。特殊的是Object的原型对象没有原型。

15.3 获取原型对象的方法

• 除了可以通过构造函数获取原型对象以外,还可以通过具体的对象来获取原型对象。
– Object.getPrototypeOf(对象)
– 对象.__proto__
– 对象. constructor.prototype
• 需要注意的是,我们可以获取到Object的原型对象,也可以对它的属性进行操作,但是我们不能修改Object原型对象的引用。

15.4 原型链


• 基于我们上边所说的,每个对象都有原型对象,原型对象也有原型对象。
• 由此,我们的对象,和对象的原型,以及原型的原型,就构成了一个原型链。
• 比如这么一个对象:
– var mc = new MyClass(123,456);
– 这个对象本身,原型MyClass.proprototype原型对象的原型对象是Object,Object对
象还有其原型。这组对象就构成了一个原型链。
– 这个链的次序是:mc对象、mc对象原型、原型的原型(Object)、Object的原型
• 当从一个对象中获取属性时,会首先从当前对象中查找,如果没有则顺着向上查找原型对象,直到找到Object对象的原型位置,找到则返回,找不到则返回undefined。

16、关键字

16.1 instanceof

• 之前学习基本数据类型时我们学习了typeof用来检查一个变量的类型。
• 但是typeof对于对象来说却不是那么好用,因为任何对象使用typeof都会返回Object。而我们想要获取的是对象的具体类型。
• 这时就需要使用instanceof运算符了,它主要用来检查一个对象的具体类型。
• 语法:
– var result = 变量 instanceof 类型

16.2 引用类型


• 上边我们说到JS中除了5种基本数据类型以外其余的全都是对象,也就是引用数据类型。
• 但是虽然全都是对象,但是对象的种类却是非常繁多的。比如我们说过的Array(数组),Function(函数)这些都是不同的类型对象。
• 实际上在JavaScript中还提供了多种不同类型的对象。

16.3 Object


• 目前为止,我们看到的最多的类型就是Object,它也是我们在JS中使用的最多的对象。
• 虽然Object对象中并没有为我们提供太多的功能,但是我们会经常会用途来存储和传输数据。
• 创建Object对象有两种方式:
– var obj = new Object();
– var obj = {}
• 上边的两种方式都可以返回一个Object对象。
• 但是第一种我们使用了一个new关键字和一个Object()函数。
• 这个函数就是专门用来创建一个Object对象并返回的,像这种函数我们称为构造函数。

16.4 Array

• Array用于表示一个有序的数组。
• JS的数组中可以保存任意类型的数据。
• 创建一个数组的方式有两种:
– 使用构造器:
• var arr = new Array(数组的长度);
• var arr = new Array(123,’hello’,true);
– 使用[]
• var arr = [];
• var arr = [123,’hello’,false];
• 读取数组中的值使用数组[索引]的方式,注意索引是从0开始的。

16.5 Date


• Date类型用来表示一个时间。
• Date采取的是时间戳的形式表示时间,所谓的时间戳指的是从
1970年1月1日0时0秒0分开始经过的毫秒数来计算时间。
• 直接使用new Date()就可以创建一个Date对象。
• 创造对象时不传参数默认创建当前时间。可以传递一个毫秒数用来创建具体的时间。
• 也可以传递一个日期的字符串,来创建一个时间。
– 格式为:月份/日/年 时:分:秒
– 例如:06/13/2004 12:12:12

    - 日期的对象,在JS中通过Date对象来表示一个时间
    - 创建对象
        - 创建一个当前的时间对象
            var d = new Date();
        - 创建一个指定的时间对象
            var d = new Date("月/日/年 时:分:秒");
            
    - 方法:
        getDate()
            - 当前日期对象是几日(1-31)
            
        getDay() 
            - 返回当前日期对象时周几(0-6)
                - 0 周日
                - 1 周一 。。。
                
        getMonth()
            - 返回当前日期对象的月份(0-11)
            - 0 一月 1 二月 。。。
        getFullYear() 从 Date 对象以四位数字返回年份。 
        
        getHours() 返回 Date 对象的小时 (0 ~ 23)。 
        getMinutes() 返回 Date 对象的分钟 (0 ~ 59)。 
        getSeconds() 返回 Date 对象的秒数 (0 ~ 59)。 
        getMilliseconds() 返回 Date 对象的毫秒(0 ~ 999)。 
        
        getTime()
            - 返回当前日期对象的时间戳
            - 时间戳,指的是从1970年月1日 0时0分0秒,到现在时间的毫秒数
                计算机底层保存时间都是以时间戳的形式保存的。
                
        Date.now()
            - 可以获取当前代码执行时的时间戳

16.6 Function


• Function类型代表一个函数,每一个函数都是一个Function类型的对象。而且都与其他引用类型一样具有属性和方法。
• 由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。
• 函数的声明有两种方式:
– function sum(){}
– var sum = function(){};
• 由于存在函数声明提升的过程,第一种方式在函数声明之前就可以调用函数,而第二种不行。

16.7 函数也可以作为参数


• 函数也是一个对象,所以函数和其他对象一样也可以作为一个参数传递给另外一个函数。
• 但是要注意的是使用函数作为参数时,变量后边千万不要加(),不加()表示将函数本身作为参数,加上以后表示将函数执行的结果作为参数。

16.8 函数对象的方法


• 每个函数都有两个方法call()和apply()。
• call()和apply()都可以指定一个函数的运行环境对象,换句话说就是设置函数执行时的this值。
• 使用方式:
– 函数对象.call(this对象,参数数组)
– 函数对象.apply(this对象,参数1,参数2,参数N)

    - call()
    - apply()
        - 这两个方法都是函数对象的方法需要通过函数对象来调用
        - 通过两个方法可以直接调用函数,并且可以通过第一个实参来指定函数中this
        - 不同的是call是直接传递函数的实参而apply需要将实参封装到一个数组中传递
    - arguments
        - arguments和this类似,都是函数中的隐含的参数
        - arguments是一个类数组元素,它用来封装函数执行过程中的实参
            所以即使不定义形参,也可以通过arguments来使用实参
        - arguments中有一个属性callee表示当前执行的函数对象
        
    - this
        - this是函数的上下文对象,根据函数的调用方式不同会执向不同的对象
            1.以函数的形式调用时,this是window
            2.以方法的形式调用时,this是调用方法的对象
            3.以构造函数的形式调用时,this是新建的那个对象
            4.使用call和apply调用时,this是指定的那个对象
            5.在全局作用域中this代表window

16.9 闭包(closure)


• 闭包是JS一个非常重要的特性,这意味着当前作用域总是能够访问外部作用域中的变量。因为函数是JS中唯一拥有自身作用域的结构,因此闭包的创建依赖于函数。
• 也可以将闭包的特征理解为,其相关的局部变量在函数调用结束之后将会继续存在

16.10 基本包装类型


• 基本数据类型是不能去调用方法的,所以JS中还提供了3个特殊的引用类型:
– Boolean
– Number
– String
• 这三个类型分别包装了Boolean、Number、String并扩展了许多实用的方法。
• 他们的使用方式和普通的对象一样。
• 要注意的是使用typeof检查这些包装类型时返回的都是object。

包装类        
    - 在JS中为我们提供了三个包装类:
        String() Boolean() Number()
        - 通过这三个包装类可以创建基本数据类型的对象
        例子:
            var num = new Number(2);
            var str = new String("hello");
            var bool = new Boolean(true);
        - 但是在实际应用中千万不要这么干。
    
    - 当我们去操作一个基本数据类型的属性和方法时,
        解析器会临时将其转换为对应的包装类,然后再去操作属性和方法,
        操作完成以后再将这个临时对象进行销毁。

16.11 Boolean


• Boolean 类型是与布尔值对应的引用类型。
• 可以采用这种方式创建:
– var booleanObject = new Boolean(true);
• 我们最好永远不要使用Boolean包装类。

16.12 Number


• Number是数值对应的引用数据类型。创建Number对象只需要在调用构造函数时传递一个数值:
– var num = new Numbaer(20);
• 使用数值时我们建议使用基本数值,而不建议使用包装类。

16.13 String


• String 类型是字符串的对象包装类型,可以像下面这样使用 String 构造函数来创建。
– var str = new String("hello world");
• 可以使用length属性来获取字符串的长度。

字符串的相关的方法
    length
        - 获取字符串的长度
    charAt()
        - 根据索引获取指定的字符
    charCodeAt()
        - 根据索引获取指定的字符编码
    String.fromCharCode()
        - 根据字符编码获取字符
    indexOf()
    lastIndexOf()
        - 从一个字符串中检索指定内容
        - 需要一个字符串作为参数,这个字符串就是要检索的内容,
            如果找到该内容,则会返回其第一次出现的索引,如果没有找到则返回-1。
        - 可以指定一个第二个参数,来表示开始查找的位置
        - indexOf()是从前向后找
        - lastIndexOf()是从后向前找
    slice()
        - 可以从一个字符串中截取指定的内容,并将截取到内容返回,不会影响原变量
        - 参数:
            第一个:截取开始的位置(包括开始)
            第二个:截取结束的位置(不包括结束)
                - 可以省略第二个参数,如果省略则一直截取到最后
            - 可以传负数,如果是负数则从后往前数
    substr()    
        - 和slice()基本一致,不同的是它第二个参数不是索引,而是截取的数量
        
    substring()
        - 和slice()基本一致,不同的是它不能接受负值作为参数,如果设置一个负值,则会自动修正为0,
            substring()中如果第二个参数小于第一个,自动调整位置
    toLowerCase() 
        - 将字符串转换为小写并返回
    toUpperCase() 
        - 将字符串转换为大写并返回
    split()
        - 可以根据指定内容将一个字符串拆分为一个数组
        - 参数:
            - 需要一个字符串作为参数,将会根据字符串去拆分数组
                可以接收一个正则表达式,此时会根据正则表达式去拆分数组
                
    match() 
        - 可以将字符串中和正则表达式匹配的内容提取出来
        - 参数:
            - 正则表达式,可以根据该正则表达式将字符串中符合要求的内容提取出来
                    并且封装到一个数组中返回
    
    replace()  
        - 可以将字符串中指定内容替换为新的内容
        - 参数:
            - 第一个:被替换的内容,可以是一个正则表达式
            - 第二个:替换的新内容
            
    search() 
        - 可以根据正则表达式去字符串中查找指定的内容
        - 参数:
            正则表达式,将会根据该表达式查询内容,
                    并且将第一个匹配到的内容的索引返回,如果没有匹配到任何内容,则返回-1。

16.14 Math


• JS 还为保存数学公式和信息提供了一个公共位置,即 Math 对象。
• 与我们在 JavaScript 直接编写的计算功能相比, Math 对象提供的计算功能执行起来要快得多。 Math 对象中还提供了辅助完成这些计算的属性和方法。

    - Math属于一个工具类,它不需要我们创建对象,它里边封装了属性运算相关的常量和方法
        我们可以直接使用它来进行数学运算相关的操作
    - 方法:
        Math.PI
            - 常量,圆周率
        Math.abs()
            - 绝对值运算
        Math.ceil()
            - 向上取整
        Math.floor()
            - 向下取整
        Math.round()
            - 四舍五入取整
        Math.random()    
            - 生成一个0-1之间的随机数
            - 生成一个x-y之间的随机数
                Math.round(Math.random()*(y-x)+x);
        Math.pow(x,y)
            - 求x的y次幂
        Math.sqrt()
            - 对一个数进行开方
        Math.max()
            - 求多个数中最大值
        Math.min()
            - 求多个数中的最小值

17、正则表达式

    - 正则用来定义一些字符串的规则,程序可以根据这些规则来判断一个字符串是否符合规则,
        也可以将一个字符串中符合规则的内容提取出来。
    - 创建正则表达式
        - var reg = new RegExp("正则","匹配模式");
        - var reg = /正则表达式/匹配模式
        
    - 语法:
        匹配模式:
            i:忽略大小写
            g:全局匹配模式
            - 设置匹配模式时,可以都不设置,也可以设置1个,也可以全设置,设置时没有顺序要求
            
        正则语法        
            | 或
            [] 或
            [^ ] 除了
            [a-z] 小写字母
            [A-Z] 大写字母
            [A-z] 任意字母
            [0-9] 任意数字
            
    - 方法:
        test()
            - 可以用来检查一个字符串是否符合正则表达式
            - 如果符合返回true,否则返回false

    - 语法:
        - 量词
            {n} 正好n次
            {m,n} m-n次
            {m,} 至少m次
            +    至少1次 {1,}
            ?   0次或1次 {0,1}
            *   0次或多次 {0,}
            
        - 转义字符
            \ 在正则表达式中使用\作为转义字符
            \. 表示.
            \\ 表示\
            . 表示任意字符
            \w
                - 相当于[A-z0-9_]
            \W
                - 相当于[^A-z0-9_]
            \d
                - 任意数字
            \D
                - 除了数字
            \s
                - 空格
            \S
                - 除了空格
            \b
                - 单词边界
            \B
                - 除了单词边界
        ^ 表示开始
        $ 表示结束

18、函数作用域练习

函数作用域练习,说出下面控制台都输出什么内容?

    <script type="text/javascript">
        var t1 = 123;
        function fun1(){
            console.log("(函数内)t1="+t1);
        }
        fun1();

        var t2 = 123;
        function fun2(){
            console.log("(函数内)t2="+t2);
            var t2 = 456;
        }
        fun2();
        console.log("t2="+t2);

        var t3 = 123;
        function fun3(){
            console.log("(函数内)t3="+t3);
            t3 = 456;
        }
        fun3();
        console.log("t3="+t3);

        var t4 = 123;
        function fun4(t4){
            console.log("(函数内)t4="+t4);
            t4 = 456;
        }
        fun4();
        console.log("t4="+t4);

        var t5 = 123;
        function fun5(t5){
            console.log("(函数内)t5="+t5);
            t5 = 456;
        }
        fun5(123);
        console.log("t5="+t5);
    </script>

答案:

19、DOM

1、什么是 DOM?

• DOM,全称 Document Object Model 文档对象模型。
• JS中通过DOM来对HTML文档进行操作。只要理解了DOM就可以随心所欲的操作WEB页面。
• 文档
– 文档表示的就是整个的HTML网页文档
• 对象
– 对象表示将网页中的每一个部分都转换为了一个对象。
• 模型
– 使用模型来表示对象之间的关系,这样方便我们获取对象。

2、节点

    - 节点(Node)
        - 节点是构成网页的最基本的单元,网页中的每一个部分都可以称为是一个节点。比如:html标签、属性、文本、注释、整个文档等都是一个节点
        - 虽然都是节点,但是节点的类型却是不同的。比如:标签我们称为元素节点、属性称为属性节点、文本称为文本节点、文档称为文档节点。
        - 常用的节点
            - 文档节点 (Document),代表整个网页
            - 元素节点(Element),代表网页中的标签
            - 属性节点(Attribute),代表标签中的属性
            - 文本节点(Text),代表网页中的文本内容

文档节点(document)
• 文档节点document,代表的是整个HTML文档,网页中的所有节点都是它的子节点。
• document对象作为window对象的属性存在的,我们不用获取可以直接使用。
• 通过该对象我们可以在整个文档访问内查找节点对象,并可以通过该对象创建各种节点对象。

元素节点(Element)
• HTML中的各种标签都是元素节点,这也是我们最常用的一个节点。
• 浏览器会将页面中所有的标签都转换为一个元素节点,我们可以通过document的方法来获取元素节点。
• 比如:
– document.getElementById()
– 根据id属性值获取一个元素节点对象。

文本节点(Text)
• 文本节点表示的是HTML标签以外的文本内容,任意非HTML的文本都是文本节点。
• 它包括可以字面解释的纯文本内容。
• 文本节点一般是作为元素节点的子节点存在的。
• 获取文本节点时,一般先要获取元素节点。在通过元素节点获取文本节点。
• 例如:
– 元素节点.firstChild;
– 获取元素节点的第一个子节点,一般为文本节点

属性节点(Attr)
• 属性节点表示的是标签中的一个一个的属性,这里要注意的是属性节点并非是元素节点的子节点,而是元素节点的一部分。
• 可以通过元素节点来获取指定的属性节点。
• 例如:
– 元素节点.getAttributeNode("属性名");
• 注意:我们一般不使用属性节点。

    - DOM操作
        - DOM查询
        - 在网页中浏览器已经为我们提供了document对象,
            它代表的是整个网页,它是window对象的属性,可以在页面中直接使用。
        - document查询方法:
            - 根据元素的id属性查询一个元素节点对象:
                - document.getElementById("id属性值");
            - 根据元素的name属性值查询一组元素节点对象:
                - document.getElementsByName("name属性值");
            - 根据标签名来查询一组元素节点对象:
                - document.getElementsByTagName("标签名");
                
        - 元素的属性:
            - 读取元素的属性:
                语法:元素.属性名
                例子:ele.name  
                      ele.id  
                      ele.value 
                      ele.className
                      
            - 修改元素的属性:
                语法:元素.属性名 = 属性值
                
            - innerHTML
                - 使用该属性可以获取或设置元素内部的HTML代码

3、事件

事件(Event)
• 事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。
• JavaScript 与 HTML 之间的交互是通过事件实现的。
• 对于 Web 应用来说,有下面这些代表性的事件:点击某个元素、将鼠标移动至某个元素上方、按下键盘上某个键,等等。

        - 事件指的是用户和浏览器之间的交互行为。比如:点击按钮、关闭窗口、鼠标移动。。。
        - 我们可以为事件来绑定回调函数来响应事件。
        - 绑定事件的方式:
            1.可以在标签的事件属性中设置相应的JS代码
                例子:
                    <button οnclick="js代码。。。">按钮</button>
            2.可以通过为对象的指定事件属性设置回调函数的形式来处理事件
                例子:
                    <button id="btn">按钮</button>
                    <script>
                        var btn = document.getElementById("btn");
                        btn.onclick = function(){
                        
                        };
                    </script>
                    
    - 文档的加载
        - 浏览器在加载一个页面时,是按照自上向下的顺序加载的,加载一行执行一行。
        - 如果将js代码编写到页面的上边,当代码执行时,页面中的DOM对象还没有加载,
            此时将会无法正常获取到DOM对象,导致DOM操作失败。
        - 解决方式一:
            - 可以将js代码编写到body的下边
            <body>
                <button id="btn">按钮</button>
                <script>
                    var btn = document.getElementById("btn");
                    btn.onclick = function(){
                    
                    };
                </script>
            </body>
            
        - 解决方式二:
            - 将js代码编写到window.onload = function(){}中
            - window.onload 对应的回调函数会在整个页面加载完毕以后才执行,
                所以可以确保代码执行时,DOM对象已经加载完毕了
            <script>
                window.onload = function(){
                    var btn = document.getElementById("btn");
                    btn.onclick = function(){
                    
                    };
                };
            
            </script> 

获取元素节点
• 通过document对象调用
1. getElementById()
– 通过id属性获取一个元素节点对象
2. getElementsByTagName()
– 通过标签名获取一组元素节点对象
3. getElementsByName()
– 通过name属性获取一组元素节点对象

获取元素节点的子节点
• 通过具体的元素节点调用
1. getElementsByTagName()
– 方法,返回当前节点的指定标签名后代节点
2. childNodes
– 属性,表示当前节点的所有子节点
3. firstChild
– 属性,表示当前节点的第一个子节点
4. lastChild
– 属性,表示当前节点的最后一个子节点

获取父节点和兄弟节点
• 通过具体的节点调用
1. parentNode
– 属性,表示当前节点的父节点
2. previousSibling
– 属性,表示当前节点的前一个兄弟节点
3. nextSibling
– 属性,表示当前节点的后一个兄弟节点

元素节点的属性
• 获取,元素对象.属性名
例:element.value
element.id
element.className
• 设置,元素对象.属性名=新的值
例:element.value = “hello”
element.id = “id01”
element.className = “newClass”

其他属性
• nodeValue
– 文本节点可以通过nodeValue属性获取和设置文本节点的内容
• innerHTML
– 元素节点通过该属性获取和设置标签内部的html代码

   

使用CSS选择器进行查询
• querySelector()
• querySelectorAll()
• 这两个方法都是用document对象来调用,两个方法使用相同,都是传递一个选择器字符串作为参数,方法会自动根据选择器字符串去网页中查找元素。
• 不同的地方是querySelector()只会返回找到的第一个元素,而querySelectorAll()会返回所有符合条件的元素。
    - 通过具体的元素节点来查询
        - 元素.getElementsByTagName()
            - 通过标签名查询当前元素的指定后代元素
            
        - 元素.childNodes
            - 获取当前元素的所有子节点
            - 会获取到空白的文本子节点
        
        - 元素.children
            - 获取当前元素的所有子元素
        
        - 元素.firstChild
            - 获取当前元素的第一个子节点
        
        - 元素.lastChild
            - 获取当前元素的最后一个子节点
        
        - 元素.parentNode
            - 获取当前元素的父元素
        
        - 元素.previousSibling
            - 获取当前元素的前一个兄弟节点
        
        - 元素.nextSibling
            - 获取当前元素的后一个兄弟节点
            
    innerHTML和innerText
        - 这两个属性并没有在DOM标准定义,但是大部分浏览器都支持这两个属性
        - 两个属性作用类似,都可以获取到标签内部的内容,
            不同是innerHTML会获取到html标签,而innerText会自动去除标签
        - 如果使用这两个属性来设置标签内部的内容时,没有任何区别的    
        
    读取标签内部的文本内容
        <h1>h1中的文本内容</h1>
        元素.firstChild.nodeValue
        
    - document对象的其他的属性和方法
        document.all
            - 获取页面中的所有元素,相当于document.getElementsByTagName("*");
            
        document.documentElement
            - 获取页面中html根元素
            
        document.body
            - 获取页面中的body元素
            
        document.getElementsByClassName()
            - 根据元素的class属性值查询一组元素节点对象
            - 这个方法不支持IE8及以下的浏览器
            
        document.querySelector()
            - 根据CSS选择器去页面中查询一个元素
            - 如果匹配到的元素有多个,则它会返回查询到的第一个元素    
            
        document.querySelectorAll()    
            - 根据CSS选择器去页面中查询一组元素
            - 会将匹配到所有元素封装到一个数组中返回,即使只匹配到一个
节点的修改
• 这里的修改我们主要指对元素节点的操作。
• 创建节点
– document.createElement(标签名)
• 删除节点
– 父节点.removeChild(子节点)
• 替换节点
– 父节点.replaceChild(新节点 , 旧节点)
• 插入节点
– 父节点.appendChild(子节点)
– 父节点.insertBefore(新节点 , 旧节点)
    document.createElement()
        - 可以根据标签名创建一个元素节点对象
        
    document.createTextNode()
        - 可以根据文本内容创建一个文本节点对象
        
    父节点.appendChild(子节点)
        - 向父节点中添加指定的子节点
        
    父节点.insertBefore(新节点,旧节点)
        - 将一个新的节点插入到旧节点的前边
        
    父节点.replaceChild(新节点,旧节点)
        - 使用一个新的节点去替换旧节点
        
    父节点.removeChild(子节点)
        - 删除指定的子节点
        - 推荐方式:子节点.parentNode.removeChild(子节点)

1.DOM对CSS的操作
    - 读取和修改内联样式
        - 使用style属性来操作元素的内联样式
        - 读取内联样式:
            语法:元素.style.样式名
            - 例子:
                元素.style.width
                元素.style.height
                - 注意:如果样式名中带有-,则需要将样式名修改为驼峰命名法
                    将-去掉,然后-后的字母改大写
                - 比如:background-color --> backgroundColor
                        border-width ---> borderWidth
                        
        - 修改内联样式:
            语法:元素.style.样式名 = 样式值
            - 通过style修改的样式都是内联样式,由于内联样式的优先级比较高,
                所以我们通过JS来修改的样式,往往会立即生效,
                但是如果样式中设置了!important,则内联样式将不会生效。
                
    - 读取元素的当前样式
        - 正常浏览器
            - 使用getComputedStyle()
            - 这个方法是window对象的方法,可以返回一个对象,这个对象中保存着当前元素生效样式
            - 参数:
                1.要获取样式的元素
                2.可以传递一个伪元素,一般传null
            - 例子:
                获取元素的宽度
                    getComputedStyle(box , null)["width"];
            - 通过该方法读取到样式都是只读的不能修改

        - IE8
            - 使用currentStyle
            - 语法:
                元素.currentStyle.样式名
            - 例子:
                box.currentStyle["width"]
            - 通过这个属性读取到的样式是只读的不能修改

    - 其他的样式相关的属性
        注意:以下样式都是只读的
    
        clientHeight
            - 元素的可见高度,指元素的内容区和内边距的高度
        clientWidth
            - 元素的可见宽度,指元素的内容区和内边距的宽度
        offsetHeight
            - 整个元素的高度,包括内容区、内边距、边框
        offfsetWidth
            - 整个元素的宽度,包括内容区、内边距、边框
        offsetParent
            - 当前元素的定位父元素
            - 离他最近的开启了定位的祖先元素,如果所有的元素都没有开启定位,则返回body
        offsetLeft
        offsetTop
            - 当前元素和定位父元素之间的偏移量
            - offsetLeft水平偏移量  offsetTop垂直偏移量
        
        scrollHeight
        scrollWidth
            - 获取元素滚动区域的高度和宽度
        
        scrollTop
        scrollLeft
            - 获取元素垂直和水平滚动条滚动的距离
            
        判断滚动条是否滚动到底
            - 垂直滚动条
                scrollHeight - scrollTop = clientHeight
                
            - 水平滚动    
                scrollWidth - scrollLeft = clientWidth
        
2.事件(Event)
    - 事件对象
    - 当响应函数被调用时,浏览器每次都会将一个事件对象作为实参传递进响应函数中,
        这个事件对象中封装了当前事件的相关信息,比如:鼠标的坐标,键盘的按键,鼠标的按键,滚轮的方向。。
    - 可以在响应函数中定义一个形参,来使用事件对象,但是在IE8以下浏览器中事件对象没有做完实参传递,而是作为window对象的属性保存
        - 例子:
            元素.事件 = function(event){
                event = event || window.event;
                
            };
            
            元素.事件 = function(e){
                e = e || event;
                
            };
            
    - 事件的冒泡(Bubble)
    - 事件的冒泡指的是事件向上传导,当后代元素上的事件被触发时,将会导致其祖先元素上的同类事件也会触发。
    - 事件的冒泡大部分情况下都是有益的,如果需要取消冒泡,则需要使用事件对象来取消
    - 可以将事件对象的cancelBubble设置为true,即可取消冒泡
        - 例子:
                元素.事件 = function(event){
                    event = event || window.event;
                    event.cancelBubble = true;
                };

4、事件深入

事件处理程序
• 我们可以通过两种方式为一个元素绑定事件处理程序:
– 通过HTML元素指定事件属性来绑定
– 通过DOM对象指定的属性来绑定
• 这两种方式都是我们日常用的比较多的,但是更推荐使用第二种方式。
• 还有一种方式比较特殊我们称为设置事件监听器。使用如下方式:
– 元素对象.addEventListener()

通过HTML标签的属性设置
• 通过HTML属性来绑定事件处理程序是最简单的方式。
<button οnclick="alert('hello');alert('world')">按钮</button>
• 这种方式当我们点击按钮以后,onclick属性中对应的JS代码将会执行,也就是点击按钮以后,页面中会弹出两个提示框。
• 这种方式我们直接将代码编写到了onclick属性中,可以编写多行js代码,当然也可以事先在外部定义好函数。
• 这种方式的优点在于,设定步骤非常简单,并且能够确保事件处理程序会在载入时被设定。
• 如果在函数的最后return false则会取消元素的默认行为。

通过DOM对象的属性绑定
• 但是其实上面的写法虽然简单,但却将JS和HTML的代码编写到了一起,并不推荐使用,我们更推荐如下的写法:
var btn = document.getElementById('btn');
btn.onclick = function(){
alert("hello");
};
• 这种写法将HTML代码和JS写在不同的位置,维护起来更加容易。

设置事件监听器
• 前边两种方式都可以绑定事件处理程序,但是它们都有一个缺点就是都只能绑定一个程序,而不能为一个事件绑定多个程序。
• 这是我们就可以使用addEventListener()来处理,这个方法需要两个参数:一个是事件字符串,一个是响应函数。
btn.addEventListener('click' , function(){alert("hello");});
• 但是要注意的是ie8以下的浏览器是不支持上边的方法的,需要使用attachEvent代替。
• 也可以使用removeEventListener()和detachEvent()移除事件。

事件处理中的this
• 在事件处理程序内的 this 所引用的对象即是设定了该事件处理程序的元素。
• 也就是事件是给那个对象绑定的this就是哪个对象。

事件对象
• 在DOM对象上的某个事件被触发时,会产生一个事件对象Event,这个对象中包含着所有事件有关的信息。包括导致事件的元素、事件的类型以及其他与特定事件相关的信息。
• 例如,鼠标操作导致的事件对象中,会包含鼠标位置的信息,而键盘操作导致的事件对象中,会包含与按下的键有关的信息。所有浏览器都支持 event 对象,但支持方式不同。

事件对象
• DOM标准的浏览器会将一个event对象传入到事件的处理程序当中。无论事件处理程序是什么都会传入一个event对象。
• 可以通过这种方式获取:
btn.onclick = function(event){
alert(event.type);
};
• Event对象包含与创建它的特定事件有关的属性和方法。触发的事件类型不一样,可用的属性和方法也不一样。

Event对象的通用属性/方法

IE中的事件对象
• 与访问 DOM 中的 event 对象不同,要访问 IE 中的 event 对象有几种不同的方式,取决于指定事件处理程序的方法。
• 在IE中event对象作为window对象的属性存在的,可以使用window.event来获取event对象。
• 在使用attachEvent()的情况下,也会在处理程序中传递一个event对象,也可以按照前边的方式使用。

事件的触发
• 事件的发生主要是由用户操作引起的。
• 比如mousemove这个事件就是由于用户移动鼠标引起的,在鼠标指针移动的过程中该事件会持续发生。
• 当指定事件被触发时,浏览器就会调用对应的函数去响应事件,一般情况下事件没触发一次,函数就会执行一次。
• 因此设置鼠标移动的事件可能会影响到鼠标的移动速度。所以设置该类事件时一定要谨慎。

事件的传播
• 在网页中标签与标签之间是有嵌套关系的,比如这样一个页面:
 

<html>
<body>
<div id="foo">
<button id="bar">sample</button>
</div>
</body>
</html>

• 如果这时用户点击了sample按钮,则会以该按钮作为事件目标触发一次点击事件。
• 这时,事件的处理将会分为捕获阶段、目标阶段、事件冒泡这三个阶段。

事件的传播
• 捕获阶段
– 这一阶段会从window对象开始向下一直遍历到目标对象,如果发现有对象绑定了响应事件则做相应的处理。
• 目标阶段
– 这一阶段已经遍历结束,则会执行目标对象上绑定的响应函数。
• 事件冒泡阶段
– 这一阶段,事件的传播方式和捕获阶段正好相反,会从事件目标一直向上遍历,直至window对象结束,这时对象上绑定的响应函数也会执行。

取消事件传播
• 我们可以使用event对象的两个方法完成:
– stopPropagation()
– stopImmediatePropagation()
• 取消默认行为:
– preventDefault()

20、BOM

1、什么是BOM


• ECMAScript无疑是JavaScript的核心,但是要想在浏览器中使用JavaScript,那么BOM(浏览器对象模型)才是真正的核心。
• BOM 提供了很多对象,用于访问浏览器的功能,这些功能与任何网页内容无关。
• BOM将浏览器中的各个部分转换成了一个一个的对象,我们通过修改这些对象的属性,调用他们的方法,从而控制浏览器的各种行为。

2、window对象


• window对象是BOM的核心,它表示一个浏览器的实例。
• 在浏览器中我们可以通过window对象来访问操作浏览器,同时window也是作为全局对象存在的。
• 全局作用域:
– window对象是浏览器中的全局对象,因此所有在全局作用域中声明的变量、对象、函数都会变成window对象的属性和方法。

3、窗口大小


• 浏览器中提供了四个属性用来确定窗口的
大小:
– 网页窗口的大小
• innerWidth
• innerHeight
– 浏览器本身的尺寸
• outerWidth
• outerHeight

4、打开窗口


• 使用 window.open() 方法既可以导航到一个特定的 URL,也可以打开一个新的浏览器窗口。
• 这个方法需要四个参数:
– 需要加载的url地址
– 窗口的目标
– 一个特性的字符串
– 是否创建新的历史记录

5、超时调用


• 超时调用:
– setTimeout()
– 超过一定时间以后执行指定函数
– 需要连个参数:
• 要执行的内容
• 超过的时间
• 取消超时调用
– clearTimeout()
• 超时调用都是在全局作用域中执行的。

6、间歇调用


• 间歇调用:
– setInterval()
– 每隔一段时间执行指定代码
– 需要两个参数:
• 要执行的代码
• 间隔的时间
• 取消间隔调用:
– clearInterval()

7、系统对话框


• 浏览器通过 alert() 、 confirm() 和 prompt() 方法可以调用系统对话框向用户显示消息。
• 它们的外观由操作系统及(或)浏览器设置决定,而不是由 CSS 决定。
• 显示系统对话框时会导致程序终止,当关闭对话框程序会恢复执行。

8、alert


• alert()接收一个字符串并显示给用户。调用alert()方法会向用户显示一个包含一个确认按钮的对话框。
• 例如:
– alert("Hello World");

9、confirm


• confirm和alert类似,只不过confirm弹出的对话框有一个确认和取消按钮。用户可以通过按钮来确认是否执行操作。
• 例如:
– confirm('你确定吗?');
• 这个函数的执行会返回一个布尔值,如果选择确定则返回true,如果点击取消则返回false。

10、prompt


• prompt会弹出一个带输入框的提示框,并可以将用户输入的内容返回。
• 它需要两个值作为参数:
– 显示的提示文字
– 文本框中的默认值
• 例子:
– prompt('你的年龄是?','18');

11、location对象


• location对象提供了与当前窗口中加载的文档有关的信息,还提供了一些导航功能。
• href属性:
– href属性可以获取或修改当前页面的完整的URL地址,使浏览器跳转到指定页面。
• assign() 方法
– 所用和href一样,使浏览器跳转页面,新地址错误参数传递到assign ()方法中
• replace()方法
– 功能一样,只不过使用replace方法跳转地址不会体现到历史记录中。
• reload() 方法
– 用于强制刷新当前页面

12、navigator对象


• navigator 对象包含了浏览器的版本、浏览器所支持的插件、浏览器所使用的语言等各种与浏览器相关的信息。
• 我们有时会使用navigator的userAgent属性来检查用户浏览器的版本。

13、screen对象


• screen 对象基本上只用来表明客户端的能力,其中包括浏览器窗口外部的显示器的信息,如像素宽度和高度等。
• 该对象作用不大,我们一般不太使用。

14、history对象


• history 对象保存着用户上网的历史记录,从窗口被打开的那一刻算起。
• go()
– 使用 go() 方法可以在用户的历史记录中任意跳转,可以向后也可以向前。
• back()
– 向后跳转
• forward()
– 向前跳转

15、document


• document对象也是window的一个属性,这个对象代表的是整个网页的文档对象。
• 我们对网页的大部分操作都需要以document对象作为起点。
• 关于document对象的内容,我们后边还要具体讲解。


http://www.kler.cn/a/162098.html

相关文章:

  • Springboot应用的端口配置方法解析与优先级详解
  • C++ 语言实现读写.csv文件.xls文件
  • 男同事36岁,听说被裁拿了12万。今天看到他退了群,但下午领导就反悔了,让他回来,还要把12万补偿退回来
  • 第二十周学习周报
  • 如何解决亚马逊商家IP问题:静态住宅IP的优势与选择指南
  • Spark中的宽窄依赖
  • 【开源视频联动物联网平台】J2mod库写一个Modbus TCP 服务器
  • 在Arch Linux上安装yay
  • Tair(1):Tair介绍
  • vue2-使用vue-i18n搭建多语言切换环境
  • gitlab-jenkins-shell-helm-chart-k8s自动化部署微服务
  • CopyOnWriteArraySet怎么用
  • 用户管理 --汇总
  • C#无标题栏窗体拖动方法
  • C#-数组池减少GC工作
  • 智能优化算法应用:基于北方苍鹰算法无线传感器网络(WSN)覆盖优化 - 附代码
  • 前端——html拖拽原理
  • Redis默认序列化方式乱码原因及解决办法
  • 谷歌正式发布最强 AI 模型 Gemini
  • C语言——常用库函数
  • 强化学习——简单解释
  • 学习spring、springmvc、mybatis、ssm所有可能用到的依赖总结,父工程pom文件依赖,<packaging>pom</packaging>
  • 2023年5个自动化EDA库推荐
  • 新概念第一册
  • python获取公网IP的三种方法
  • Vue.filter