Blogger Information
Blog 38
fans 0
comment 0
visits 23426
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
JavaScript语法基础1--2018-9-12
晓明的博客
Original
966 people have browsed it
  1. javascript是什么? 有什么用?
        (1).javascript是最流行的,而且是唯一的写"前端脚本"的编程语言;
        (2).前端主要是指:html,css,javascript,以及相关的开发框架,函数库等,共同特征就是指可以直接在浏览器中运行;
        (2).脚本语言的一个基本特征是,可以使用标签,以元素的形式直接嵌入到html文档中,例如<script></script>,<?php ?>;
        (3).javascript功能极其强大,强大到令人发指,前后端几乎通吃,但它最主要的功能仍是实现用户与页面的交互操作;

    ---------------------------------------------------------------------------------------------------

    2. 如果将js代码写到html中?
        (1). 使用标签:<script>,它是双标签
        (2). 可以添加一个属性 type="text/javascript"表示脚本的类型,但考虑到js是前端唯一并且是默认脚本,所以推荐省略掉
        (3). js代码可以写到<script></script>标签中,类似css中页内样式,仅限当前文档使用
        (4). 如果想将js代码应用到更多的html文档中,可以在起始标签<script src="js.js">添加src属性,指定一个外部js文件
            类似css中的外部样式表,实现脚本共享,这也是js最常用的方式,写到独立文件中,不仅可页页共享,还能缓存,提升加载速度.
        (5). <script>中引入外部脚本时,其标签内的js代码将会被忽略.
        (6). 浏览器是可以禁用js的,但这种情况极期罕见,毕竟大多应用是基于js,所以大家在学习时可以忽略用户是否禁用js脚本.

    ---------------------------------------------------------------------------------------------------

    3. js运行结果的三种输出方式
        (1). alert()弹窗 let site = 'php中文网'; alert(site);
        (2). write()方法: document.write(site);
        (3). console.log()控制台: console.log(site);

    4.. 基本语法:
        (1).字面量[值]: 'php中文网';  99; js中,字面量非常强大,将功能发挥到了极致,一定要格外重视
        (2).变量[名称/标识符]: 临时存放数据的地方,就是数据的占位符而已,例如:site = 'php中文网'; price = 99;
        (3).操作符:主要有算术运算(+,-,*,/,=)与逻辑运算(==,!==,===,<,>...)二类,重点是操作符对操作数的类型转换;
            例如: 15 + 20 // 35;    '15' + 20 // 1520,字符串拼接;
        (4).注释: 与php类似, 单行//,多行 /* ... */;
        (5).语句: 用分号';'结束,分号并非必须有,可以省略,近些年越多越多的开发者都开始省略分号,但在学习阶段,为了避免入坑,推荐加上;

    5. js脚本的基本组成部分: 变量和函数,下面咱们先聊聊变量:
       (1). 变量使用ESC6标准的: let声明, 函数使用 function 声明;
       (2). 传统的使用var声明,不支持块作用域,并且允许重复声明,let完美的解决以上问题,推荐使用;
       (3). 什么是块作用域? if(){...}, for(){...},之前js只支持一种函数作用域,这和php是一样的;
       (4). php到目前为止,仍不直接支持块作用域,可以使用其它技术来模拟,使用闭包等;
       (5). var 和 let 声明变量的区别:
            1. let支持块作用域,var不支持
            if (true) {
               var n = 100;     // var声明,块作用域外部可以拿到
               let n = 100;     //let声明,块作用域外部拿不到
           }
           console.log(n);
           2. let不允许重复定义,var允许
           let name = 'peter';
           let name = 'zhu';  // 报错
           var salary = 5800;
           var salary = 6800; // 不报错
       (6). let 变量声明时未初始化,默认值为undefined,undefined是一种特殊的类型,一会再说
       (7). let 变量提升时,会报引用错误,而var会输出undefined,所以推荐必须先声明再初始化,或者声明初始化二合一;
       (8). 以后尽可能使用let来声明和使用变量,大家把var 忘了吧

    6. 变量的数据类型
        (1). js数据类型分为二大类: 原始类型与引用类型; js不允许自定义数据类型,因为js是动态的,可以模拟出任何类型,不需要自定义
        (2). 原始类型有五种: String字符串,Number数值(不区分整数和浮点数),Boolean布尔,Undefined未定义,Null类型
        (3). 引用类型:[Object对象, Array数组]重点掌握,Function函数, Date日期,RegExp正则, 包装对象...
        (4). 类型检测: typeof ,只能检测出: 原始类型与函数,其它都返回Object,
            typeof 'abc'    // "string"
            typeof 100      // "number"
            typeof true     // "boolean"
            typeof null     // "object" ,正确应该返回:"null",这是历史遗留问题,暂时无解
            typeof undefined    // "undefined"
            typeof [1,2,3]      // "object"
            typeof {x:1,y:2}    // "object"
            typeof function f1(){}  // "function"

            对于引用类型,应该使用 instanceof

            let o = {x:1,y:2}
            o instanceof Object     // true

            instanceof 检测数组类型是会有问题:
            [1,2,3] instanceof Array    // true
            [1,2,3] instanceof Object   // true,因为数组也是对象,返回true也应该是对的
            正确方法应该是使用Array的isArray()方法
            Array.isArray([1,2,3])      // true
            Array.isArray({x:1,y:3})    // false
            Array是数组对象的构造函数,一会再说

    --------------------------------------------------------------------------------------------------

    ---------------------------------------------------------------------------------------------------

    7. 函数:
        在学习之前,咱们先学点其它的玩意:
        现在跟着我大写朗读三遍: "js中,一切皆对象"
        只是牢记这句话,后面的课程,你才会搞明白,否则从根上就把你干蒙逼了~~~


        (1).函数是js中的一等公民,不仅是代码执行的基本单元,也是创建其它成员的基本类型;
        (2).函数按功能分为二大类: 普通函数,构造函数;
        (3).按创建方式分为: 函数声明,函数表达式,匿名函数,自执行函数;
        (4).函数声明自动提前:因为函数如此重要,所以函数声明会自动提升到代码最前面,不论在脚本的什么地方声明,都可以直接使用;
        (5).函数调用必须使用函数名加上一对圆括号;
        (6).函数中可以使用return 返回结果,如果没有return 语句,函数执行完毕,会返回 undefined ;
            function f1() {}
            f1()    // undefined
            function f2(){return 'php.cn'}
            f2()    // "php.cn"
        (7).每次执行函数,都会自动创建一个函数作用域,与外部临时隔离,函数外部成员在函数作用域内可见,反之则不行;
            let m = 100;        // 该变量声明在函数外部,全局范围内可见
            function f3() {
                return m +50;   //函数外声明的变量全局可见
            }
            f3()    // 150

            function f4(){
                let n = 20; //函数内声明的变量,外部不可见
            }
            m +n    // n 未定义,出错
        (8).函数表达式
            表达式通常会返回一个确定的值,所以可以直接将表达式用到需要值的地方
            let f5 = function (){ return 200; }
            150 + f5()      // 350, f5()可直接看到一个值,内容就是调用f5()函数的结果
        (9).匿名函数:主要用做函数的参数
            [1,2,3,4].filter(function(item,index,array){return item>2;})
        (10).自执行函数:声明完直接运行,不需要调用
            (function(a,b){return a+b;})(20,40)     // 60

      (11)函数的参数问题:
        1. js根本不在乎函数有没有参数,以及参数有多少,是什么类型;
        2. 因为在内部是使用一个数组来接收这些参数,并使用对象 arguments 来访问这个数组
        3. 因此函数中的参数只是一个实际参数的占位符而已,仅起提示作用,所以也叫: "命名参数"
        4. 命名参数仅提供了访问便利,并非必要;
        5. arguments对象, 可以像使用数组一个使用它,例如:arguments[1],但它并不是Array对象的实例;
        6. arguments.length 属性中保存着参数的数量
        7. js中没有函数签名,不存在函数重载(相同的签名,不同的实现)
        7. 但是js可以用动态参数来模拟重载: 案例:根据参数不同,执行不同的操作
            //声明
            function add() {
                var num = arguments.length
                switch (num) {
                    case 0:
                        return '至少要有一个参数'
                        break
                    case 1:
                        return arguments[0]
                        break
                    case 2:
                        return arguments [0]+arguments[1]
                        break
                    case 3:
                        return arguments[0]+arguments[1]+arguments[2]
                        break
                    default:
                        return '参数过多'
                }
            }

            //调用
            add() // '至少要有一个参数'
            add(100) // 100
            add(100,200)  // 300
            add(100,200,300) // 600
            add(100,200,300,400) // '参数过多'


    ---------------------------------------------------------------------------------------------------

    8. 数组 Array


        1. Array 是仅次于 Object 外使用频率最高的引用类型;
        2. Array 是有序列表,每一个数组元素可以保存任何类型的数据;
        3. Array 的长度是可以动态调整的,自动增长;
        4. 与Object类似,创建Array数组也有二种式: 实例化构造函数Array, 字面量

            (1). 构造函数Array
            var arr = new Array()  //实例化Array(),创建空数组
            var arr = new Array(3) // 创建的新数组有三个预置元素,默认值都是undefined
            var arr = new Array(3,5,'a') //一个或一个以上非数值元素,就是创建实际的内容而非长度
            var arr = Array([1,2,3],'php','html') //可省略new,可传入数组等多种类型给构造函数

            (2). 字面量
            var arr = ['html','css','javascript']; //字面量
            var arr = []; // 空数组

            无论使用哪一种方式,都会有二个默认的属性:
            1. length: 数组元素的数量
            2. __proto__:
        5. length 属性的特殊用途:
            (1). Array.length : 是可读可写的,可人为设置,实现数组元素的移除与添加;
            (2). Array.length : 它的值始终比元素最大索引大1,可以用作永远指向下一个元素的索引;
            (3). 添加元素
                var arr = []  // 空数组
                arr[arr.length] = 100  // arr.length = 0,等价于arr[0] = 100
                arr[arr.length] = 200
                arr[arr.length] = 300
            (4). 删除元素
                var arr = ['html','css','javascript','jquery','vue.js']
                arr.length   // 当前数组长度: 5 ,即有5个元素
                arr[arr.length-1]   // 获取最后一个元素的值: 'vue.js'
                arr.length -= 1    // 将数组长度减1, 即当前数组长度更新为: 4
                arr[arr.length-1]  // 获取最后一个元素的值: 'jquery'
        6. 创建新数组
            (1):基于当前数组中的所有项,创建一个新数组: concat()
                var arr = [1,2,3]
                arr.concat(4,5)     //  
                arr.concat([6,7,8]) // 接受数组参数,这个数组会拆开,将每一个元素并入原数组中:[1, 2, 3, 6, 7, 8]
            (2).基于数组的开始与结束的位置来创建: slice() 单词本意: 切开
                slice(起始索引[,结束索引]),如省略结束索引,默认为后面全部数据
                var arr = [10,20,30,40,50]
                arr.slice(2)        // 从索引2开始,获取后面全部内容: [30, 40, 50]
                arr.slice(1,4)      // 从索引1开始,到索引4结束(不含索引4): [20, 30, 40]
            (3).向数组中间插入数据: splice(), 功能主要是: [删除,插入,替换]
                参数说明: splice(start,length,value...)
                1). 删除
                arr.splice(起始,删除数)
                var arr = [10,20,30,40,50]
                arr.splice(0,2)     // 从头部0,开始删除2个,返回删除的元素: [10, 20]

                2). 插入
                arr.splice(起始,0,要插入项)
                arr.splice(1,0,88,99) //第二个参数0,表示插入,插入的数据是第三个参数
                //本例是从第二个元素起,插入二个新元素:88,99:
                arr     // 查看当前数组: [30, 88, 99, 40, 50]

                3). 替换
                arr.splice(起始,删除数,要插入项)//第二个参数1,表示替换,
                arr.splice(2,1,'dog','cat')     // 返回删除项: 99
                arr     // 查看数组: [30, 88, "dog", "cat", 40, 50]

              7. 栈方法
           (1).数组可以模拟栈操作
           (2).栈是一种LIFO(Last_In_First_Out)'后进先出'的数据结构,插入与删除只能是栈顶(一端)进行
           (3).push()入栈, pop()出栈
           (4).举例
               var arr = []     // 创建空数组
               arr.push(10,20)  // 将数组看成栈,入栈二个元素,10先入,20后入,返回数组长度:2
               arr              // 查看当前数组: (2) [10, 20]
               arr.length       // 查看当前数组长度: 2
               arr.push([1,2])  // 入栈一个数组元素,返回长度: 3
               arr              // 查看数组: (3) [10, 20, (2) [1, 2]
               arr.pop()        // 出栈(栈顶元素出栈):  (2) [1, 2]
               arr.pop()        // 继续出栈: 20

           8. 队列方法
           (1).与栈方法相对的是队方法:FIFO(First_In_First_Out):先进先进
           (2).因为栈方法:push()可以从数组未端添加元素,所以只需要一个方法可以从前端获取元素即可
           (3).从数组前端获取元素的方法就是:shift(),并自动将数组长度减1;
           (4):push() + shift() 实现队操作:尾进头出
               var arr = [10,20,30]
               arr.push(40)     // push()尾部入队: 40
               arr.length       // 此时数组长度是: 4
               arr              // 查看队列: (4) [10, 20, 30, 40]
               arr.shift()      // shift()从前端(头部出队),返回出队元素: 10,长度自动减1
           arr.length           // 当前数组长度是: 3
           (5):unshift(),可以在数组前添加任意数组的元素,并更新数组长度,与栈方法pop()配合实现队操作
           (6):unshift() + pop() 实现队操作:头进尾出
               var arr = [10,20,30]
               arr.unshift(3,5)     // unshift()入队操作: 头部添加二个新元素,并自动更新长度
               arr.length           // 新长度: 5
               arr                  // [3,5,10,20,30]
               arr.pop()            // pop()出队操作: 返回出队元素: 30,并更新长度
               arr.length           // 新长度: 4

     9. 重排序方法
            (1).反转: reverse()
            var arr = [1,2,3,4,5]
            arr.reverse()       // 数组元素翻转:(5) [5, 4, 3, 2, 1]

            (2).sort()更加的灵活
            var arr = [10,4,22,8,2]
            arr.sort()      // [10, 2, 22, 4, 8]:显然错误,因为sort()默认将元素视为字符串,'10'显然是小'2'
            //解决方案: sort()可接受一个回调参数,在回调函数中进行比较运算完成正确排序
            function compare(val1,val2){
                if (val1 < val2) {
                    return -1
                } else if (val1 > val2) {
                    return 1
                } else {
                    return 0
                }
            }

            ***对于数值型元素的比较,这个回调函数可以进行简化:
            function compare(val1,val2) {
                return val - val2  //升序
            }

            arr.sort(compare)       // 输出正确结果:[2, 4, 8, 10, 22]
            //如果改为降序排列,只需要改变回调中的返回值即可
            function compare(val1, val2) {
                return val2-val1   //降序: 用第二个参数减去第一个参数即可
            }

            arr.sort(compare)   // 降序: [22, 10, 8, 4, 2]

     10. 位置方法
            (1). indexOf(要查找的项 [,起始位置]): 从头部开始,查找失败返回: -1
            (2). lastIndexOf(要查找的项 [,起始位置]): 从尾部开始,查找失败返回: -1
            (3). 实例:在数组中查找指定元素并返回索引:
                 var arr = [1,2,3,4,5,4,3,2,1]
                 arr.indexOf(4)         // 查找4,返回4在数组中的索引位置: 3
                 arr.indexOf(4,4)       // 传入第二参数,指定从索引4开始查找,返回索引位置: 5
                 arr.lastIndexOf(4)     // 从尾部查找4,返回4第一次出的索引位置: 5
                 arr.lastIndexOf(4,4)   //从尾部查找4,从索引4开始,跳过了5,所以输出索引位置: 3
    11. 迭代方法
            (1). 5个方法都可以接受2个参数:每一顶上运行的回调函数(必选),运行该函数的作用域[可选](影响this的值)
            (2). 这几个方法不会影响到原数组的值
            (3). 五个方法介绍:
                 (1). every():如果每一项运算都返回true,则返回true;
                 (2). some(): 任一项运算返回true,则返回true;
                 (3). filter(): 返回true项组成的新数组;
                 (4). forEach(): 每一项执行给定函数,无返回值;
                 (5). map(): 返回每次执行结果组成的新数组
            (4). 举例:
                 (1). every()
                 var arr = [1,2,3,4,5,6]
                 // 要求每一项都必须大于2,才可以返回true,显示第1,2个元素不符合要求
                 arr.every(function(item,index,array){ return item > 2 })
                 (2). some()
                 // 只要数组元素中有一个元素值大于2,就满足条件并返回true
                 arr.some(function(item,index,array){ return item > 2 })
                 (3). fileter()
                 // 返回数组中元素值大于2的元素,组成的新数组
                 arr.filter(function(item,index,array){ return item > 2 })
                 (4). forEach():注意无返回值,不要使用return ,常用来遍历数组
                 //输出全部的元素值
                 arr.forEach(function(item,index,array){ console.log(item) })
                 //输出元素的索引
                 arr.forEach(function(item,index,array){ console.log(index) })
                 // 输出当前正在遍历的数组元素:注意会把当前数组输出6遍
                 arr.forEach(function(item,index,array){ console.log(array) })


        12. 归并方法
            (1). 本质是数组元素之间的二二计算,并把结果带到下一次的运算中;
            (2). reduce(): 从第一项开始迭代,直到计算出一个最终值;
            (3). reduceRight(): 从最后一项开始迭代,向前遍历直到第一项;
            (4). 都可以接受二个参数: 1迭代的函数,2是可选的归并初始值
            (5). 迭代函数有四个参数: prev前一个,cur当前,index索引,array数组
                var arr = [1,2,3,4,5]
                // 计算:1+2+3+4+5的值
                // 计算过程:
                // 1 + 2 = 3
                // 3 + 3 = 6
                // 6 + 4 = 10
                // 10 + 5 = 15
                arr.reduce(function(prev,cur,index,array){return prev+cur})     // 结果: 15

                //给reduce(callback,init)传入第二参数,计算的初始值: 10
                arr.reduce(function(prev,cur,index,array){return prev+cur},10)  // 结果: 10 + 15 = 25

                // reduceRight()功能与reduce()完全一致,只是计算方向从右边开始
                arr.reduceRight(function(prev,cur,index,array){return prev+cur})    // 15
                arr.reduceRight(function(prev,cur,index,array){return prev+cur},10) // 25

    ---------------------------------------------------------------------------------------------------

    9. Object 类型
        1.创建Object实例:
            (1). 构造函数
             var obj = new Object()
             obj.name = 'Peter'
             obj.age = 29
            (2). 字面量
            var obj = {
                name: 'Peter',
                age: 29
            }
        2. 表达式上下文: 花括号出现在赋值操作右边,就是一个表达式上下文,左花括号就是表达式的开始;
        3. 语句上下文: 花括号出现在语句上下文中,例如 if/while...,则是语句块的开始;
        4. 用字面量创建实例,最后一个属性后不要添加','号;
        5. 属性名可以用字符串: var obj = {'name': 'zhu', 'sex': 'male'}
        6. 可以创建一个只包含默认属性和方法的实例: var obj = {}  // obj只有默认属性和方法,等价于new Object()
        7. 案例,根据参数是否有指定属性,输出对应的内容
        function displayInfo(args) {
            var output = ''

            if (typeof args.name == 'string') {
                output += 'Name: ' + args.name + '\n'
            }

            if (typeof args.age == 'number') {
                output += 'Age: ' + args.age + '\n'
            }

            console.log(output)
        }

        displayInfo({name: '朱老师', age: 30})  // Name: '朱老师' Age: 30
        displayInfo({name: '朱老师'})  //  Name: '朱老师'
        displayInfo({age: 30})  //  Age: 30
        displayInfo({'age': 30})  //  Age: 30
        displayInfo({})   // 空

        可以,无论输入什么,都可以得到正确的结果;
        8. 通常情况下,必选参数使用命名参数比较好,当有多个可选参数时使用对象字面量时行封装会更灵活;

        9. 刚才都是使用的点'.'语法来访问实例中的属性,支持属性名是标识符或字符串,其实也支持方括号;
        10.使用方括号语法与数组类似,但是实例的属性/方法名必须放到引号中: obj['name']
        var obj = {name:'peter', age: 30}
        console.log(obj['name'])
        console.log(obj['age'])
        11.方括号语法还支持变量属性名:
        var a = 'name'
        var obj = {name:'zhu'}
        obj.a // undefined
        obj[a] // 'zhu'

    *******************************************************************************************

    对象的扩展知识:
    一、对象的生成:
        (1).对象字面量
            1. 使用字面量生成对象的三种场景:
                (1): 单例模式(singleton);
                (2): 多值数据(函数的参数与返回值)
                (3): 替代构造函数来生成对象
            2. 场景一:单例模式
                (1).所谓单例:将类的实例对象数量限定为一个;
                (2).类是对象的模板,可以多次实例化,创建多个实例对象;
                (3).如果只需要一个实例对象,但么就没必要去创建类了;
                (4).所以使用字面量直接创建一个单例对象是最方便的啦.
                var obj = {name:'peter', name:30}

            3. 场景二: 多值数据的使用场景[类似于关联数组]
                (1). 给函数传递多个参数
                [传统方式:]
                function getData(x, y, z) {
                    return (x+y+z)
                }
                getData(1,2,3)  // result: 6

                [对象字面量做为函数调用的实参]
                function getData(data) {
                    return (data.x+data.y+data.z)
                }
                getData({x:1, y:2, z:3})  // result: 6

                [对象字面量做为默认参数]
                //如果调用时没有传入实参
                function getData(data) {
                    //函数内修改参数值并不是一个好习惯
                    data = data || {x:1, y:2, z:3}
                    return (data.x+data.y+data.z)
                }
                getData()  // result: 6

                [对象字面量做为函数返回值]
                function func() {
                    return {x:4, y:5, z:6}
                }
                func()  // {x:4, y:5, z:6}

                [扩展知识,返回数组,并实现将数组中元素转为独立变量的技巧]
                function func() {
                    return [4, 5, 6]
                }
                [x,y,z]=func()  // 将数组中的元素转为独立的变量
                x   // x = 4
                y   // y = 5
                z   // z =6

            4. 场景三: 代替构造函数
                (1). 构造函数是用来创建对象的,所以只需要将对象字面量做为函数返回值即可;
                (2). 从语法上看,与返回多值数据基本相同,区别在于执行方式;
                (3). 实例:
                function createObj() {
                    //直接将对象字面量做为返回值
                    return {
                        x: 10,
                        y: 20,
                        z: 30,
                        sum: function () {
                            return this.x + this.y + this.z
                        }
                    }
                }

                var obj = createObj()
                obj.sum()   // 结果: 60
                createObj().sum()   //使用链式调用进行简化

            (2). 构造函数与new表达式
                1. 构造函数是一种必须要通过new表达式调用的特殊函数;
                2. 构造函数的用途是用来创建对象(类的实例化);
                3. 因为类可以被实例化为对象,所以类中必须要有该实例对象的代言人;
                4. 这个特殊的类中对象的代言人,就是伪变量: this
                5. 构造函数基本用法:
                    (1).声明: function MyClass(x, y) {
                                this.x = x
                                this.y = y
                             }
                    (2).调用: var obj = new MyClass(10,20)
                             obj.x  // 10
                             obj.y  // 20
                6. 总结:
                    (1).构造函数本身与普通函数声明形式是相同的;
                    (2).构造函数是通过"new"表达式来调用;
                    (3).new 表达式的值: 新对象的引用
                    (4).new 表过式是通过构造函数内的this引用了新生成的对象

                (一).new 表达式的操作
                    new 操作的完整流程
                    1. new 表达式 首先是新生成一个"操作对象"(可视为一个通用对象,是对象就具备访问属性和调用方法的能力);
                    2. 用这个"操作对象"调用指定的函数(即构造函数);
                    3. 构造函数内部有一个内部指针:this,指向了这个由"new"表达式新生成的操作对象;
                    4. 在构造函数中,可以使用this为当前操作对象添加属性或方法;
                    5. 构造函数执行完成,将会返回该操作对象的引用:this, 做为new 表达式的 "值"
                    6. 即: new 操作 的最终返回值,其实就是构造函数中的: this

                (二).构造函数的调用
                    1. 其实任何函数都可以通过 new 来调用,所以任何函数都可以充当构造函数的角色;
                    2. 但只有一个函数内部使用了this,他才是一个构造函数,可以生成一个新对象;
                    3. 构造函数结尾会隐式一条: return this 语句,返回当前对象的引用;
                    4. js中的构造函数类似于其它语言中的类,但却又比他们难以理解,毕竟new一个函数来生成一个对象比较特殊;
                    5. 而其它语言,都是 new 一个类,而js中没有类的概念,所以构造函数,实际上就起到了"类"的作用;
                    6. 因为构造函数起到了"类"的作用,所以按照惯例,充当构造函数的函数名,首字母应该大写,以示不同;

    ---------------------------------------------------------------------------------------

    八、属性的访问
        1. 属性访问:
            (1).点语法,只能使用标识符: obj.name;
            (2).中括号[],必须使用字符串,可用用字符串字面量,也可以用字符串变量
            var obj = {name:'peter', age:20}
            obj.name    // 'peter'
            obj['age']  // 20
            var p = 'name'
            obj[p]  // 'peter'

            ({x:40,y:50}).x // 40,说明访问属性的是对象的引用
            ({x:40,y:50}).y // 50
            实际开发过程中,可能遇不到直接对字面量对象进行运算,但是在链式调用很方便
        2. 属性设置与访问的规则相同:
            var o = {}
            o.name = 'jack'
            o['age'] = 30

        3. 属性值的更新
            1.将属性表达式写在"="号左侧
            obj.name = 'zhu'    // 如果属性存在则是更新,如果不存在就是创建新属性
            delete obj.name     // 删除对象obj上的属性name
        4.点运算符与中括号运算符的区别
            1. 能使用点运算符"."的场景,一定能使用中括号运算符"[]",反之则不一定;
            2. 访问属性首选点运算符,当"."会产生歧义时,则使用中括号来规避,例如属性名是一个非法标识符
            3. 以下三种情况必须使用中括号:
                (1).使用了非法标识符: 属性名多个单词之间有空格,连接线-或特殊字符$#%.等
                (2).使用了变量属性名: var p = 'name'; obj[p];
                (3).使用了表达式的属性名:
                var obj = {x:10, y:20}
                var m = 5       // 定义变量 m ,初始值为5
                obj[ (m<10)? 'x' : 'y']     // m当前值小于10,返回true,此时输出obj.x的属性值: 10
                var m =13       // 更新m, 使其大于10
                obj[ (m<10)? 'x' : 'y']     // m当前值大于10,返回true,此时输出obj.y的属性值: 20

        5.属性的枚举: for (var key in obj) { console.log(obj.key) }

    *******************************************************************************************

    变量的扩展知识:

    一、变量的声明
        1. 变量可以用来表示某个值,或某个变量;
        2. 变量使用前应该先声明:var m ;
        3. 声明未赋值(初始化); 默认为: undefined;
        4. 对同一个变量可以重复声明;
        推荐语法:
        var a = a || 10;    //已声明则用原值,未声明用默认值
        var a ;     // 已声明未初始化,默认值:undefined
        var a = 40;  // 40  // 初始化40

    --------------------------------------------------------------

    二、变量与引用
        1. 变量分为: 基本类型, 引用类型;
        2. 变量赋值: 值传递, 引用传递;
        3. 基本类型变量也叫值型变量,复制采用值传递,二者是完全独立的;
        4. 引用类型变量与叫引用变量,类似于C语言指针,二者共同指向同一对象;

        基本类型:
        var a = 123;
        var b = a;  // a 值 传递 给 b
        b++ // b 自增1
        b   // b=124
        a   // a无变化

        引用类型
        var a = {x: 10, y: 20};
        b = a;  // 将对象a复制到b中,对象是引用赋值,a和b指向同一个对象
        b.x     // 10
        b.x = 30;  // 将b.x 属性重新设置为30
        a.x         // a.x 属性同步被更新为30
        a = {a: 88, b: 99}  // 改变a变量的值,使其引用另一个对象
        a   // 查看对象a, 它的值已发生变化: {a: 88, b: 99}
        b   // 查看b,发现仍是原来的对象内容:{x:30,y:20}
        此时原对象的引用保存在变量b中,这与证明了对象变量的确是引用类型


        函数的参数
        1. 函数传参是使用值传递方式进行;
        2. 经典案例:交换二个变量的值

        var a = 100;
        var b = 200;
        //swap()实现交换
        function swap(a,b) {
            return [b, a];
        }

        [a,b] = swap(a,b);  //执行交换操作

        a   // a等于200
        b   // b等于100

        字符串与引用
        1. 字符串是基本类型,基本类型的值都是不可改变的;
        2. 字符串内部仍是按引用方式来实现的,但表现为值传递;

        引用总结
        1. 赋值应该是从右向左看: var a = {x:1,y:2};
        2. 应该是先有一个对象{x:1,y:2},然后再声明一个标识符a来引用它;
        3. 所以无论是否存在变量a, 对象{}都是客观存在的;
        4. 因此,即使变量a指向了其它对象: var a = {m:5,n:6},而对象{x:1,y:2}仍存在
        5. 当对象{x:1,y:2}没有任何引用指向时,系统将启动回收机制销毁该对象

    --------------------------------------------------------------

    二、变量与属性

        (1)全局变量与全局对象之间的关系:
            1. 在js中一切皆对象,所有变量就是属性,属性就是变量;
            2. 变量或属性名的用途: 获取值[右值] 或者 被赋值[左值];
            3. 根据作用域: '全局变量' 和 '局部变量(函数参数)';
            4. 全局变量: 函数之外声明的变量;
            5. 局部变量: 函数内部声明的变量;
            6. 全局变量(包括全局函数名)是"全局对象"的属性;
            7. 全局对象: 程序一旦开始运行,就会被自动创建;
            8. 证明: 全局变量 === 全局对象的属性
            var x = 'foo'   // 声明全局变量并初始化'foo'
            x   // 以全局变量方式访问 'foo'
            this    // 查看当前全局对象, 浏览器中的js是: window
            this.x  // 以对象属性方式访问全局变量x

            9. 如果将全局对象,赋值给一个全局变量,做为该对象的引用的话
            var global = this   // 声明全局变量global, 用全局对象this初始化

            10.这时,全局变量,他具有双重身份: 1. 全局变量; 2. 全局对象this的引用
            这就是传说中的: 自己引用自己
            'global' in this    // 返回: true, 说明全局变量global的确是this(全局对象)的属性
            global  // 返回 window对象, 说明 global 本身的确是全局对象

            11. 这种自引用关系,在js中非常常用,例如在客 户端javascript中,就提供了一个引用了全局对象的
            全局变量:window, 这个window 就类似于我们上面创建的全局变量global的作用.
            12. 全局对象和全局变量的生命周期: 从脚本开始运行直到脚本结束(关闭当前页面).

        (2)局部变量与对象之间的关系
            1. 函数内部声明的变量,以及函数的参数都是局部变量;
            2. 与全局变量一样,局部变量也会被隐式的声明为某个对象的属性;
            3. 这个隐式的对象就是: call;
            4. 局部变量的生命周期: 通常从函数调用直到函数执行结束返回调用者;
            5. 可以通过一种称作:"闭包"的技术,打破这个约束,使局部变量离开函数仍可以使用.

    --------------------------------------------------------------

    四、变量的查找
        1. 无论是左值,还是右值操作,都会触发对变量名称的查询操作;
        2. 在最外层代码(函数之外)的变量查找,实际上查找的是全局对象的属性(全局变量与全局函数);
        3. 在函数内部的变量名查找,因为在函数内部可以使用全局变量,所以首先是查找call对象的属性,
            如果没找到,再到全局对象属性上查找,是由内到外的顺序进行: call对象 --> global对象

    --------------------------------------------------------------

    五、对变量或属性是否存在的检测
        (1):对变量是否存在进行检测(以全局变量为例):
            1. 常用语法: var a = a || 10; // a有值由用原值,否则使用默认值:10
            2. 变量复制: var a; var b = a || 10;  // 原理同上
            3. 变量复制: var a; var b = a != undefined ? a : 10; // 判断a是否有值
            4. 利用js没有块级作用域特征,使用typeof 进行再精确的判断
            var a
            if (typeof a != undefined) {
                var b = a
            } else {
                var b = 10
            }
            b++     //因为没有块级作用域,所以这里可以使用变量 b
            5.以上都必须先对a进行声明,其实可以用 'in' 判断是否是某对象的属性来判断:in this
            if ( 'm' in this) {var n = m} else {var n = 20} //然后就可以使用变量n了

        (2):对属性是否存在进行检测:
            1. 属性存在时,与变量一样,返回它的值;
            2. 当属性不存在时,与变量的返回完全不同;
            3. 访问不存在的变量会返回错误,而属性只会返回undefined

            age     // 返回错误
            this.age    // undefined

    ---------------------------------------------------------------------------------------

    js中的流程控制:
    与其它编程语言一样,也有分支与循环二大类,语法与php基本一致
    1. 判断
        (1).单分支: if () {}
        (2).双分支: if(){} else {}
        (3).多分支: if(){} else if () {} else {}
        (4).switch: switch(n) {
                case 1:
                    break;
                ...
                default:
                break;
            }
    2. 循环
        (1). for(let i=0; i<n; i++) {...}
        (2). while(){...}   /  do {...} while()
        (3). for in:   for (let var in obj)


Correction status:Uncorrected

Teacher's comments:
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post