JavaScript的组成、ECMAScript、ES6的语法、ES6的新特性、Map集合、函数、类、类的继承

一、JavaScript的组成

1. ECMAScript:JavaScript的基本语法

2. BOM:浏览器对象模型(操作浏览器)—- 核心对象 window

3. DOM:文档对象模型(操作html文档)—- 核心对象document

二、ECMAScript

1. ECMAScript5:脚步语言。不需要独立的编译器,通过浏览器加载运行。实现用户和页面的交互

2. ECMAScript6:是JavaScript的下一代语法标准,于2015年6月发布。是JavaScript正式成为企业级的开发语言

3. ECMAScript和JavaScript的关系:

​     ECMAScript是一个语法规范,JavaScript是该语法规范的实现

三、ES6的语法

1. let 和const

​ (1)let:用来声明块级变量。var声明的变量会出现作用域的提升(会出现变量的污染)

​ (2)const:声明的常量必须要初始化

​ (3)const声明的对象:常对象

​       1)可以修改对象的属性值,但是不能修改对象本身

const obj = { 
    name:'张三',
    age:25
}
obj.name = '李四'  //正确的:修改对象的属性
obj = {} // 错误的:不能改变对象

​       2)冻结对象:不能修改对象的属性。使用Object.freeze(对象名)

const obj = {
            name:'李四',
            age: 25
        }
console.log(obj)
Object.freeze(obj) //冻结对象obj,就不能修改obj的属性
obj.name = '王五'
console.log(obj)

​       3)冻结嵌套的对象

       hasOwnProperty(key)函数:判断key是否是对象的属性,若是返回true,不是返回false

       遍历对象的属性:for…in

​​        for(let k in obj){ }

const p = {
            name:'李四',
            age: 25,
            family:{
                father:'李世民',
                mother:'长孙皇后'
            }
        }
    //定义一个冻结函数
    function fun(obj){ //函数的参数是对象
        //1.冻结对象:参数接收的对象
        Object.freeze(obj)
        //2.使用for...in循环遍历对象的属性
        for(let key in obj){ //key = 'mother'
            //2.1 hasOwnProperty用来判断对象是否包含给定的属性。typeyof用来判断数据类型
            if(obj.hasOwnProperty(key) && typeof obj[key] === 'object'){// obj['mother'] -- string
                fun(obj[key])
            }
        }
    }
    fun(p)
    p.family.father = '李建成'
    console.log(p)

​       4)构造函数

​        a. 作用:初始化对象(是对象的模型),所有的对象都是用这个模型造出来的

​       ​ b. this:指向由构造函数创建的对象(代表当前对象)

​​        c. 对象:是属性和行为的结合体

​ ​       属性:是对象的静态特征(成员变量)

​       ​ 行为:是对象的动态特征(函数 / 方法)

<script>
        /*需求:定义构造函数Student,属性分别是:id、name、html、css、JavaScript
             (1)创建5个Student对象,把这5个对象存入数组
             (2)找出总成绩最高的对象
             (3)根据javascript成绩对数组进行降序排序
        */
       //1.定义构造函数
        function Student(id,name,html,css,javascript){
            //1.1 定义属性:this后的是属性
            this.id = id
            this.name = name
            this.html = html
            this.css = css
            this.javascript = javascript
            //1.2 定义方法:求对象的总成绩
            this.total = function(){
                return this.html + this.css + this.javascript
            }
        }
        //2.创建对象,然后将对象存入数组
        let s1 = new Student(101,'贾宝玉',78,85,95)
        let s2 = new Student(102,'贾元春',65,88,98) 
        let s3 = new Student(103,'贾探春',75,65,88)
        let s4 = new Student(104,'贾迎春',90,80,92)
        let s5 = new Student(105,'贾惜春',72,78,86)
        let arr = [s1,s2,s3,s4,s5] //arr数组称为对象数组
        console.log(arr)
        //3. 找总成绩最高的
        let max = arr[0]  //假定数组中第一个对象的总成绩最高
        for(let i=1;i<arr.length;i++){
            if(arr[i].total() > max.total()){
                max = arr[i]
            }
        }
        console.log("总成绩最高的是:",max)
        //4.按JavaScript的成绩进行降序排序
        for(let i=0;i<arr.length;i++){
            for(let j=0;j<arr.length-1;j++){
                if(arr[j].javascript < arr[j+1].javascript){
                    let t = arr[j]
                    arr[j] = arr[j+1]
                    arr[j+1] = t
                }
            }
        }
        console.log(arr)
    </script>

四 、ES6的新特性

1. 临时死区:用let和const声明的变量,放在‘临时死区’,使用let声明的变量、const声明的常量的作用域不会被提升

2. 在循环中使用var的情况

        let arr=[]
        for(var i=0;i<5;i++){  //var定义的i是全局的,若将var改成let,则输出0 1 2 3 4
            arr.push(function(){  //arr是一个函数数组:数组的每个单元都是函数
                console.log(i);
            })
        }
        arr.forEach(function(item){  //item是函数:输出5个5
            item();
        })

 3. 解构赋值:Rest运算符:”

​ (1)当迭代器使用:会按顺序遍历容器中的元素

function fun(x,y,z){
            console.log(x,y,z)
        }
        let arr = [11,22,33]
        fun(...arr) //'...'运算符的作用是一个迭代器:依次遍历数组中的元素

 (2)替代函数的内置属性arguments

function fun(...args){
            console.log(args)
        }
        let arr = [11,22,33]
        fun(arr)

 (3)通过解构赋值可以简化变量的赋值

let arr = [11,22,33]
let [a,b,c] = arr
console.log(a)

(4)通过”…”把特定的元素放在变量里

let [a,...arr] = [11,22,33]  //将11赋给a,将22,33赋给arr,arr就是一个数组
console.log(a)
console.log(arr)

 (5)通过解构来交换变量的值

let a = 10
let b = 20; //必须要以分号结尾
[a,b] = [b,a]
console.log(a,b)

4. 对象的解构

​ (1)将对象的属性解构出来赋给变量

let obj = {
            id:1001,
            userName:'关羽',
            sex:'男'
        }
        let { id,userName,sex } = obj  //变量名必须和对象的属性名相同
        console.log('编号:',id)
        console.log('用户名:',userName)
        console.log('性别:',sex)

  (2)解构多层对象

let obj = {
            id:1001,
            userName:'关羽',
            sex:'男',
            score:{
                html: 98,
                css:95,
                js: 85
            }
        }
        let { id,userName,sex,score:{html,css,js} } = obj  //变量名必须和对象的属性名相同
        console.log('编号:',id)
        console.log('用户名:',userName)
        console.log('性别:',sex)
        console.log('css的成绩:',css)

 (3)在解构时可以给变量取别名

let obj = {
            id:1001,
            userName:'关羽',
            sex:'男',
            score:{
                html: 98,
                css:95,
                js: 85
            }
        }
        let { id:userId,userName:name } = obj  //userId是id的别名,name是userName的别名
        console.log('编号:',userId)
        console.log('用户名:',name)
        console.log('性别:',sex)

5. 模板字符串:使用反引号``和${ 变量名 } 将字符串常量和变量写在一个串里。就不需要使用’+’进行字符串的拼接

6. Symbol类型

​ (1)ES5的数据类型:numberstringbooleanbigintnullundefinedobject

​ (2)ES6新增的Symbol:表示一个唯一的值

       1)直接创建:let 变量名 = Symbol

<script>
    let s1 = Symbol
    let s2 = Symbol
    console.log(s1 == s2)//true
</script>

       2)间接创建:传字符串 let 变量名 = Symbol(字符串)

<script>
    let a1 = Symbol('abc')
    let a2 = Symbol('abc')
    console.log(a1 === a2)//false
    let obj = {
        a1:'asd',
        a2:'aqw'
    }
</script>

7. Set集合:是一种数据结构,里面不能存放重复的值。可以用于数组去重、字符串去重

​ (1)创建方式:

       1)使用new运算符:let 变量 = new Set()

<script>
    let s1 = new Set()//创建一个空集合
    console.log(s1)
</script>

       2)通过数组来创建:let 变量名 = new Set( [1,2,3,5,6] ) ,去除重复的元素

<script>
    let arr = [1,2,34,6,5,4,3,2,6,4]
    let s2 = new Set(arr)
    console.log(s2)
</script>

(2)常用的方法:

       1)add(val):向集合中添加元素

       2)delete(val):删除集合中的元素。删除成功返回true,删除失败返回false

       3)has(val):判断val在集合中是否存在,若存在返回true,不存在返回false

       4)clear():清空集合,没有返回中

       5)values():获取的是集合中所有value

       6)keys():获取集合中的key

        let s1 = new Set()//创建一个空集合
        console.log(s1)

        let arr = [1, 2, 3, 2, 0, 3, 5]
        let s2 = new Set(arr)
        console.log(s2)

        let temp = s1.add('table')
        console.log(typeof temp)
        s1.add(123).add(456).add('abc')
        // console.log(s1)//集合
        // console.log(...s1)//解构
        // console.log([...s1])//将集合转换成数组

        let flag = s1.delete(123)
        console.log(flag)
        console.log(...s1)

        let f = s1.has('table')
        console.log(f)

        s1.clear()
        console.log(s1)

        let t =s1.values()
        console.log('values:',t)

        let k =s1.keys()
        console.log('keys:',k)

强调:Set集合也是key-value格式,它的key和value是相同的

​ (3)属性:size 存放的是集合中元素的个数

​ (4)遍历方法:

       1)for … of

		for(let i of s1.keys()){
            console.log(i);
        }
        console.log('Size:',s1.size);

       2)forEach

        s1.forEach(function(value,key){
            console.log(value+'--------'+key)
        })

(5)集合运算

       1)并集

        let setA = new Set([4, 5, 6])
        let setB = new Set([5, 6, 7])
        //实现setA与setB的并集
        let bj = new Set([...setA, ...setB])
        console.log(bj)

       2)交集

<script>
    let set1 = new Set([12,3,4,2])
    let set2 = new Set([2,3,45])
    // 2.实现set1与set2的交集:通过过滤器实现
    // [...set1]解构集合set1,将其转换成数组
    let t = [...set1]
    // console.log(t)
    // 对t进行过滤:使用filter函数
    let t1 = t.filter(function(item){//依次从t中取出元素传递给item,在函数体内设置筛选条件,将满足条件的元素赋给t1
        return set2.has(item)//将满足条件的item返回
        // 上下等价
        if (set2.has(item)) {
            return item
        }
    })
    console.log(t1)
</script>

       3)差集

		let setA = new Set([4, 5, 6]);
        let setB = new Set([5, 6, 7]);
         /*2.实现setA与setB的交际:通过过滤器实现
        [...setA]:解构集合setA,将其转换为数组
        */
        let arr = [...setA];  //解构集合setA,将其转换为数组
        //对arr进行过滤:使用filter函数
//第一种
        let temp = arr.filter(function (item) {  //依次从arr中取出元素传递给item,在函数体内设置筛选的条件,将满足条件的元素返回给temp
            // return setB.has(item);  //将满足条件的item返回(简写)
            if(setB.has(item) == false){
                return item
            }
        })
        console.log(temp);
//第二种
 
        let t = [...setA].filter(function (item) {
            return setB.has(item);
        })
        console.log(t);

问题1:创建Set集合时为什么用new运算符?

             Set是一个构造函数,凡是用构造函数创建对象时都要用new

问题2:Set构造方法的参数为什么是数组或null?

             底层代码规定的

8. WeakSet集合:只是一个对象集合。即集合中只能存放对象。它支持 add,has 和 delete 方法

<script>
    let obj1 = {
        name:'cc',
        age:18
    }
    let ws = new WeakSet([{'a':23}])
    ws.add(obj1)
    console.log(ws)
       
    console.log(ws.has())
 
    ws.delete(obj1)
    console.log(ws)
</script>

五、Map集合

1. 数据的存放格式:采用 key-value(键值对) 的方式进行存放。采用这种方式存放数据的有

​ (1)对象:属性对应的是key(键),属性值对应的是value(值)

        let obj1 = {
            name:'kk',
            age:14
        }

​ (2)JSON:是常用的一种前后台数据交换的格式

2. Map的定义:Map是一种数据结构(Hash结构),在ES6中是Map一种存放许多键值对的有序列表

3. Map的使用方法

​ (1)属性:size —- 存放的是Map中的元素个数

​ (2)方法

       1)Map():构造方法。用来创建Map对象,不带参数表示创建空的Map,即size属性值为0

        let m1 = new Map()//构造方法,创建Map对象
        console.log('size:',m1.size)

       2)set(key,value):向Map中添加数据

        let m1 = new Map()//构造方法,创建Map对象

        m1.set('name','张三')//set,向Map中添加数据
        m1.set('USA','美国')
        m1.set('CHINA','中国')
        m1.set('INA','印度')

       3)get(key):获取键为key的value

        let m1 = new Map()//构造方法,创建Map对象
        
        m1.set('name','张三')//set,向Map中添加数据
        m1.set('USA','美国')
        m1.set('CHINA','中国')
        m1.set('INA','印度')

        console.log(m1.get("name"));

       4)has(key):判断Map中是否存在key

        let m1 = new Map()//构造方法,创建Map对象
        
        m1.set('name','张三')//set,向Map中添加数据
        m1.set('USA','美国')
        m1.set('CHINA','中国')
        m1.set('INA','印度')

        console.log(m1.has("INA")); 

       5)delete(key):删除key

console.log(m1.delete('US'))

       6)clear():清空Map

       7)keys():返回Map中的所有key

console.log(m1.keys())

课堂练习1:以“key” <===> “value”,显示一个Map

强调

(1)Map中的key不能重复,但是value可以重复

(2)keys()返回的是Map中所有key集合 —— keys()返回的集合类型是Set

(3)在Map中通过key可以得到对应的value,反之则不行

       8)values():返回Map中的所有value

        for(let a of map.values()){
            console.log(a)
        }

       9)entries():可以获取Map的所有成员(即所有的key-value)

for (const temp of map.entries()) {//.entries()可以不写
    console.log(temp)
}
// or
for (const [key, value] of map.entries()) {
    console.log(`${key}:${value}`)
}

       10)forEach循环遍历

map.forEach(function (value, key) {//第一个参数是value,第二个是key
    console.log(`${key}:${value}`)
})

练习     Map数组(数组的每个单元都是一个key-value)的使用

let m1 = new Map()
           m1.set('XA','西安')
           m1.set('XY','咸阳')
        let m2 = new Map()
            m2.set('K1','重庆')
            m2.set('K2','成都')
        let m3 = new Map()
        let arr = [m1,m2,m3]   //arr是Map数组
        console.log(arr)
        //输出'西安'
        console.log(arr[0].get('XA'))

4. Map转换为数组

​ (1)解构整个Map

let m4 = new Map([
[‘one’,’北京’],
[‘two’,’上海’],
[‘three’,’深圳’]
])
    let arr = [...m4.entries()]  //将m4转换成数组.arr本质是3行2列的二维数组
    console.log(arr)

(2)解构keys()

let a1 = [...m4.keys()]  //将Map的所有key转换成数组
       console.log(a1)

(3)解构values()

let a2 = [...m4.values()]//将Map的所有value转换成数组
       console.log(a2)

六、函数

1. ES5中的函数:

​ (1)通过function关键字定义函数

         ​ function 函数名([参数]){ }

​ (2)函数表达式

         ​ ​ let 变量 = function([参数]){ }

注意:

​ (1)形参和实参的区别

​ (2)函数的返回值:return语句来实现

2. ES6中对函数的扩展

​ (1)函数形参的默认值

function fun(a,b,c=45){ //形参c的默认值为45,如果调用函数时没有给c传递参数值,则使用默认值
            console.log('a=',a)
            console.log('b=',b)
            console.log('c=',c)
        }
        let a = 10,b = 20,c = 30
        fun(a,b)

(2)箭头函数:在定义函数时使用“=>”符号。在定义回调函数(高阶函数)、函数表达式时使用。可以简化代码

<script>
        //1.函数没有参数,函数体语句只有一条
        let fun = ()=> "张三"
        // let du =()=>'dd'
        let du =()=>{return 'dd'}
        //大括号省略,默认含有返回的功能
        console.log(du())

        //2.函数带有一个参数,可以省略‘()’
        let f2 = args =>{
            console.log(args)
        }
        f2(1024)//函数调用,将1024传递给形参args

        //3.箭头函数带有多个参数
        let f3=(arg1,arg2)=>arg1+arg2
        //等价于
        // let f3 = (arg1,arg2)=>{return(arg1+arg2)}
        console.log(f3)

        //4.函数体只有一条语句,函数返回对象:必须用'()'将对象包起来
        let f4 = ()=>({
            name:'张三',
            age:25
        })
        console.log(f4())

        window.id='宝塔镇河妖'
        //5.箭头函数中this的绑定问题
        let obj = {
            id:'s101',
            f5:function(){
                console.log(this.id)//this代表obj
            },
            f6:()=>{
                console.log(this.id)//输出undefined,因为箭头函数没有绑定this,这时this指向离它最近的上层对象
            }
        }
        obj.f5()
        obj.f6()

        //6.箭头函数没有内置的arguments
        let pt = ()=>{
            console.log(arguments)//Uncaught ReferenceError: arguments is not defined
        }
        pt(12,23,34)
</script>

 七、类

1. 面向对象:是一种开发思想,一切皆为对象。对象是属性和行为的结合体

2. 面向过程:也是一种开发思想。开发中的每个细节,开发者都要考虑到。

3. 类:具有相同属性和行为的对象的集合

4. ES5中实现类的功能:构造函数,在构造函数中封装了属性和方法。缺陷是构造函数和普通函数的定义方式是一样的

5. ES6中类的定义方式:语义性更强、语法更简洁

​ class 类名{

​                  属性

​                  ​行为

​                 ​ }

class 是关键字,专门用来定义类。

    <script>
        //1.用class定义Student类
        class Student{
            constructor(id,name,sex){//构造函数.this后面的id,name,sex是属性
                this.id = id
                this.name = name
                this.sex = sex
            }
            display(){
                console.log('学号:',this.id)
                console.log('姓名:',this.name)
                console.log('性别:',this.sex)

            }
        }
        //2.使用Student类创建对象:创建对象时不能显式地使用constructor,必须用类名创建,默认调用类的构造即constructor函数
        let s1 = new Student(101,'令狐冲','男')
        let s2 = new Student(102,'郭靖','男')
        let s3 = new Student(103,'黄蓉','女')

        //3.使用对象
        s1.display()
        console.log('----------------------')
        s2.display()
        console.log('----------------------')
        s3.display()
    </script>

6. ES6中支持getter/setter来获取属性值、设置属性值

​ (1)定义get方法、set方法的目的是:用于隐藏对象的属性名

​ (2)在使用get方法、set方法方法时不用带’()’

<script>
    class Account{
        constructor(id,pwd){
            this._id = id//加'_'的属性,称为私有属性(是语义上的区分)
            this._pwd = pwd
        }
        // 1.定义get方法:获取属性的值
        get id(){
            return this._id
        }
        get pwd(){
            return this._pwd
        }
        // 2.定义set方法:设置属性值
        set id(value){
            this._id = value
        }
        set pwd(value){
            this._pwd = value
        }
    }
    let a1 = new Account('1001','123456')
    console.log('账号:',a1.id)//a1.id实际调用的是id()方法
    console.log('密码:',a1.pwd)//a1.pwd实际调用的是pwd()方法,因为pwd()方法前有get,因此调用时不用带'()'
    console.log('--------------------------')
    a1.id = '1002'//实际调用的是set id(value)方法
    a1.pwd = '111111'//实际调用的是set pwd(value)方法
    console.log('账号:',a1.id)
    console.log('密码:',a1.pwd)
</script>

7. 类的属性和方法(函数):类可以有属性也没有没有属性,可以有方法也可以没有方法

8. 类的属性是放在构造方法中初始化的,若类没有属性,可以不显式定义构造方法,此时,系统会自动生成一个无参的空的构造方法

八、类的继承

1. 基本的概念

​ (1)父类(基类):可以派生子类的类

​ (2)子类(派生类):由父类派生而来的类

2. 继承的好处

        在父类中定义的属性和方法,子类继承后就可以直接使用。

3. 面向对象的三大特性

​ (1)封装性:对象是属性和行为的封装体 —- 数据安全

​ (2)继承性:子类可以继承父类的属性和方法 —- 代码复用

​ (3)多态性:同一个消息传递给不同对象,出现的效果不同 —- 应用灵活、可以适应不同的需求

4. 继承的实现

​ (1)ES5中继承的实现:没有类的概念

         1)构造函数:构造函数名就是类名,在ES5中类的继承实际就是构造函数的继承

         2)实现:通过call、apply、bind函数来实现构造函数的继承

//1.定义构造函数:基类
        function Fatcher(name){
            this.name = name
            this.age = 45
        }
        //2.定义构造函数:子类
        function Son(name){
            /* this代表是上层对象(window),name参数传递个Father构造函数。
               等于在Son函数中调用了Father函数:Son就具有了name和age属性(相当于从Father继承了name和age)
            */   
            Fatcher.call(this,name)  //函数劫持,在Son中通过call调用Father构造函数,将参数name传递给Father构造函数
            this.height = '178cm' //height是Son自己的属性
            this.show= function(){
                console.log('姓名:',this.name)
                console.log('年龄:',this.age)
                console.log('身高:',this.height)
            }
        }
        let son = new Son('赵四')
        son.show()

(2)ES6中的继承:通过关键字extends实现

//1.定义父类Fatcher
        class Fatcher{
            constructor(name,age){
                this.name = name
                this.age = age
            }
            fun(){
                console.log('我是父类中的方法......')
            }
        }
        //2.定义子类Son,继承自Father类
        class Son extends Fatcher{
            constructor(name,age){
                super(name,age); //调用父类的构造函数
            }
            hobby(){
                console.log('我喜欢篮球')
            }
            show(){
                console.log('姓名:',this.name)
                console.log('年龄:',this.age)
            }
        }
        let s1 = new Son('张三',25)
        s1.hobby()
        s1.show()
        s1.fun()

 A、super:指向父类。super([参数])表示调用父类的构造函数

​ B、如果在子类的构造函数中调用父类的构造函数,那么super()必须作为子类构造函数中的第一条语句

​ 在执行子类的构造函数之前必须先执行父类的构造函数(先有父,后有子)

​ C、方法覆盖(Overwrite):在继承过程中,若父类的某个方法与子类的某个方法同名,则子类方法覆盖父类的同名方法

​ D、在子类的方法中可以使用super调用父类中的某个方法

​ E、不允许多继承,只能单继承

​ 多继承:类的直接父类有多个

​ 单继承:类的直接父类只有一个父类

5. 类继承过程中的向上转型

       子类对象的类型一定是父类的类型,父类对象的类型不能是子类的类型

       1)typeof:用于判断变量的数据类型(基本数据类型)

​             typeof 变量名 == ‘数据类型’​

​       2)instanceof:用于判断变量的数据类型(类类型)

​ ​            对象名 instanceof 类名

​​            判断”对象”是否是给定的类的对象

class Sports{
    constructor(){}
    play(){}
}
class FootBall extends Sports{
    constructor(){
        super()
    }
    play(){
        console.log('足球是用脚踢的......')
    }
}
class Bascketball extends Sports{
    constructor(){
        super()
    }
    play(){
        console.log('篮球是用手打的......')
    }
}
function howToPlay(sp){
    sp.play()
}
let sport = new Sports() //sport是基类的对象
let foot = new FootBall()
let flag = (foot instanceof Sports) //子类对象foot是父类Sports类型 --- 向上转型
console.log("flag= ",flag) //flag = true
let flag = (sp instanceof FootBall) //父类对象sp不能是子类FootBall类型 --- 不能向下转型 
console.log("flag= ",flag)  //flag = false
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值