• JavaScript ES6(一)


    一、面向对象编程介绍

    1、面向过程编程(POP)

    • 分析出解决问题所需要的步骤
    • 用函数把这些步骤一步一步实现
    • 使用的时候再一个一个依次调用
    • 举例
      • 大象装冰箱
        • 打开冰箱
        • 装进大象
        • 关闭冰箱

    2、面向对象编程(OOP)

    • 把事务分解成一个个对象

    • 由对象之间分工与合作

    • 以对象功能来划分问题,而不是步骤

    • 举例

      • 大象装冰箱
        • 大象(对象)
          • 进入冰箱
        • 冰箱(对象)
          • 开门
          • 关门
    • 面向对象的特性

      • 封装性
      • 继承性
      • 多态性

    3、面向对象与面向过程对比

    • 面向过程
      • 优点
        • 性能比面向对象高,适合跟硬件联系很紧密的东西,例如单片机就采用的面向过程编程
      • 缺点
        • 没有面向对象易维护、易复用、易扩展
    • 面向对象
      • 优点
        • 易维护、易复用、易扩展,由于面向对象由封装、继承、多态性的特性,可以设计出低耦合的系统,使系统,更加灵活,更加易于维护
      • 缺点
        • 性能比面向过程低

    二、ES6中的类和对象

    1、面向对象思维特点

    • 抽取(抽象)对象共用的属性和行为组织(封装)成一个类(模板)
    • 对类进行实例化,获取类的对象

    2、对象

    在JavaScrrpt中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象。

    对象是一个具体的事物。实实在在看的见,摸得着。

    对象是由属性和方法组成

    • 属性:事物的特征,在对象中用属性来表示(常用名词)
    • 方法:事物的行为,在对象中用方法来表示(常用名词)

    3、类(class)

    在ES6中新增加了类的概念,可以使用class关键字声明一个类,之后以这个类来实例化对象

    类抽象了对象的公共部分,它泛指某一大类(class)

    对象特指某一个,通过实例化一个具体的对象

    4、创建类

    // 结构
    class name {
        // class body
    }
    
    // 创建实例
    new name()
    
    // 举例
    
    // 1、创建 class 创建一个 明星类
    // 类名首字母大写,类名后没有小括号
    class Star{
        // constructor函数:构造函数
        // 构造函数不需要加function
        // 可以接收传递过来的参数,同时返回实例对象
        // constructor函数只要new生成实例时,就会自动调用这个函数
        // 如果我们不写constructor函数,类也会自动生成这个函数
        constructor(uname){
            this.uname = uname;
        }
    }
    
    // 2、利用类创建对象
    // 生成实例 new 不能省略,类名后加小括号
    var ldh = new Star('刘德华')
    console.log(ldh.uname); // 刘德华
    

    5、类中添加方法

    class Star{
        constructor(uname){
            this.uname = uname;
        }
        // 类中函数不需要写function
        // 多个函数之间,不用逗号分隔
        sing(sang){
            console.log(sang)
        }
    }
    var ldh = new Star('刘德华')
    ldh.sing('冰雨')
    

    6、类的继承

    class Father{
        constructor(){
        }
        firstName(){
            console.log('张')
        }
    }
    class Son extends Father{
    }
    
    var son = new Son();
    son.firstName() // 张
    

    7、super关键字

    用于访问和调用对象父类上的函数。

    可以调用父类的构造函数,也可以调用父类的普通函数

    // 调用构造函数
    class Father{
        constructor(x,y){
            this.x = x;
            this.y = y; 
        }
        sum(){
            console.log(this.x + this.y)
        }
    }
    class Son extends Father{
        constructor(x,y){
            super(x,y); // 调用了父类中的构造函数 
        }
    }
    var son = new Son(1,2)
    son.sum()
    
    class Father{
        say(){
            console.log('Father')
        }
    }
    class Son{
        say(){
            console.log('Son')
        }
    }
    class Son1 extends Father{
        say(){
            console.log('Son1')
        }
    }
    class Son2 extends Father{
        say(){
            super.say()
        }
    }
    var son = new Son()
    son.say() // Son
    var son1 = new Son1()
    son1.say() // Son1
    var son2 = new Son2()
    son2.say() // Father
    
    // 就近原则
    // (1) 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有,先执行子类
    // (2) 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法
    

    8、子类扩展自己方法

    class Father{
        constructor(x,y){
            this.x = x;
            this.y = y; 
        }
        sum(){
            console.log(this.x + this.y)
        }
    }
    // 子类继承父类 sum 方法。同时扩展 substract 方法
    class Son extends Father{
        constructor(x,y){
            // 利用 super 调用父类的构造函数
            // super 必须在 this 之前调用
            super(x,y);
            this.x = x;
            this.y = y;
        }
        substract(){
            console.log(this.x - this.y)
        }
    }
    var son = new Son(5,3)
    son.substract()
    

    9、类和对象使用注意点

    • 在ES6中类没有变量提升,所以必须先定义类,才能通过类实例化对象
    • 类里边的的共有属性和方法一定要加this使用
    • 类中this指向问题
      • constructor中的this,指向的是,创建的实例对象
      • 方法中的this指向这个方法的调用者

    二、构造函数和原型

    1、实例成员和静态成员

    • 实例成员

      • 构造函数内部通过this添加的成员
      • 实例成员只能通过实例化的对象访问
    • 静态成员

      • 在构造函数本身添加成员
      • 只能通过构造函数来访问
    function Star(uname,age){
        this.uname = uname;
        this.age = age;
        this.sing = function () {
            console.log('唱歌')
        }
    }
    // 实例成员
    var ldh = new Star('刘德华')
    console.log(ldh.uname) // 刘德华
    ldh.sing()	// 唱歌
    console.log(Star.uname) // undefined
    // 静态成员
    Star.sex = '男'
    console.log(Star.sex) // 男
    console.log(ldh.sex) // undefined
    

    2、构造函数的问题

    • 存在浪费内存的问题
    • 使用prototype存放方法解决

    3、原型对象(prototype)

    prototype:构造函数原型

    构造函数通过原型分配的函数是所有对象所共享的。

    JS规定,每个构造函数都有一个prototype属性,指向另一个对象。

    这个prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。

    function Star(uname,age){
        this.uname = uname;
        this.age = age;
    }
    // 一般情况下,公共属性定义到构造函数里边,公共的方法放到原型对象上
    Star.prototype.sing = function () {
        console.log('唱歌')
    }
    var ldh = new Star('刘德华')
    var zxy = new Star('张学友')
    ldh.sing()
    zxy.sing()
    

    4、对象原型(__proto__)

    对象身上系统添加一个__proto__指向我们构造函数的原型对象prototype

    方法的查找规则:

    • 首先,查找对象本身有没有该方法
    • 如果没有,因为__proto__存在,就去构造函数原型对象prototype查找
    function Star(uname,age){
        this.uname = uname;
        this.age = age;
    }
    // 一般情况下,公共属性定义到构造函数里边,公共的方法放到原型对象上
    Star.prototype.sing = function () {
        console.log('唱歌')
    }
    var ldh = new Star('刘德华')
    console.log(ldh.__prototype === Star.prototype) // true
    

    5、构造函数(constructor)

    对象原型和构造函数原型对象都有一个属性constructor,成为构造函数,因为它指回构造函数本身

    • 作用
      • 主要记录该对象引用于哪个构造函数
      • 可以让原型对象重新指向原来的构造函数

    6、原型链

    // 以Star类举例
    Star对象实例.__proto__ = Star.prototype
    Star.prototype.__proto__ = Object.prototype
    Object.prototype.__proto__ = null
    
    构造函数.prototype = 原型对象
    原型对象.constructor = 构造函数
    

    7、成员查找机制

    • 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性
    • 如果没有,就查找它的原型(也就是__proto__指向的prototype原型对象)
    • 如果还没有,就查找原型对象的原型(Object的原型对象)
    • 依此类推,一直找到Object为止(null)

    8、原型对象中this指向

    • 在构造函数中,this指向的是对象实例
    • 在原型对象中,this指向的是对象实例

    9、扩展内置对象

    // 给数组增加自定义求偶数和的功能
    Array.prototype.sum = function (){
        var sum = 0;
        for(var i=0;i<this.length;i++){
            sum += this[i]
        }
        return sum;
    }
    
    var arr = [1,2,3]
    console.log(arr.sum())
    

    三、继承

    ES6之前并没有提供extends继承。可以通过构造函数+原型对象模拟实现继承,被称为组合继承

    1、call()

    • 调用函数
    • 修改函数运行时的this指向
    fun.call(thisArg,arg1,arg2, ...)
    // fun:函数
    // thisArg:当前调用函数this的指向对象
    // arg1,arg2:传递的其他参数
    
    // 定义函数
    function fn(){
        console.log('喝咖啡')
        console.log(this)
    }
    // 定义对象
    var o = {
        name:'张三'
    }
    
    // 1、调用函数
    fn.call() // 喝咖啡
    		  // window 对象
    
    // 2、修改函数运行时的`this`指向
    fn.call(o)	// 喝咖啡 
    			// { name:'张三'}
    

    2、借用父构造函数继承属性

    // 父构造函数
    function Father(uname,age){
        // this 指向父构造函数的对象实例
        this.uname = uname;
        this.age = age;
    }
    
    // 子构造函数
    function Son(uname,age,sex){
        // this 指向子构造函数的对象实例
        Father.call(this,uname,age)
        this.sex = sex;
    }
    
    var son = new Son('andy',18,'男')
    console.log(son) // 获得son对象
    

    3、借用原型对象继承方法

    // 父构造函数
    function Father(){}
    Father.prototype.firstName = function () {
        console.log('张')
    }
    // 子构造函数
    function Son(uname,age,sex){}
    // 借用原型对象继承方法
    Son.prototype = new Father();
    // 如果不将构造函数重新指回Son,此时为Father的构造函数
    Son.prototype.constructor = Son;
    

    4、类的本质

    • 类的本质其实还是一个函数。可以简单的理解为 构造函数的另外一种写法。

    四、ES5新增方法

    1、遍历数组(forEach)

    array.forEach(function (currentValue,index,arr))
    // currentValue:数组当前项的值
    // index:数组当前项的索引
    // arr:数组本身
    
    var arr = [1,2,3];
    var sum = 0;
    arr.forEach(function (value,index,array) {
        console.log('每个数组元素:' + value)
        console.log('每个数组元素的索引号:' + value)
        console.log('数组本身:' + array)
        sum += value;
    })
    console.log(sum) // 6
    

    2、遍历数组(filter)

    array.filter(function (currentValue,index,arr))
    // currentValue:数组当前项的值
    // index:数组当前项的索引
    // arr:数组本身
    
    // filter:创建一个新数组,新数组中的元素是通过检查指定数组中符合条件的所有元素,主要用于筛选
    
    var arr = [12,66,4,88];
    var newArr = arr.filter(function (value,index,array) {
        return value >= 20;
    })
    console.log(newArr) // [66,88]
    

    3、遍历数组(some)

    array.some(function (currentValue,index,arr))
    // currentValue:数组当前项的值
    // index:数组当前项的索引
    // arr:数组本身
    
    // some()方法用于 查找数组中是否有满足条件的元素
    // 注意它返回值是布尔值,如果查找到这个元素,就返回true;查找不到返回,false
    // 如果找到第一个满足条件的元素,则终止循环,不再继续查找
    
    var arr = [10,30,4]
    var flag = arr.some(function (value,index,array) {
        return value >= 20;
    })
    console.log(flag) // true
    

    4、字符串两端删除空白字符(trim)

    str.trim()
    
    // trim本身不影响原字符串本身,它返回的是一个新的字符串
    

    5、Object.defineProperty

    定义对象中新属性或修改原有的属性

    Object.defineProperty(obj,prop,descriptor)
    
    // obj:对象(必需)
    // prop:需定义或修改属性的名字(必需)
    // descriptor:目标属性所拥有的特性(必需),有以下值供选择
    // 		value:设置属性的值,默认undefined
    //		writable:值是否可以重写。true|false 默认false
    //		enumerable:目标属性是否可以被枚举。true|false 默认false
    //		configurable:目标属性是否可以被删除或是否可以再次修改特性。true|false 默认false
    
    var obj = {
        id:1,
        pname: '小米',
        price: 1999
    }
    
    Object.defineProperty(obj,'num',{
        // 添加 num: 1000
        value: 1000
    })
    
    Object.defineProperty(obj,'id',{
        // 不可修改id的值
        writable: false
    })
    
    Object.defineProperty(obj,'address',{
        // 添加 address: '中国'
        value: '中国'
        // 不允许被遍历。例如用Object.keys()时
        enumerable: false
    })
    
    Object.defineProperty(obj,'id',{
        // 不允许被删除
        configurable: false
    })
    
    Object.defineProperty(obj,'id',{
        // 此处修改id的其他三个特性,都编程true
        // 但是因为上一步中(configurable: false)的设置,则不允许,修改其他特性
        writable: true,
        enumerable: true,
        configurable: true
    })
    

    6、Object.keys

    获取对象所有属性

    Object.keys(obj)
    
    // 效果类似:for...in...
    // 返回一个由属性名组成的数组
    

    该内容学习自 传智播客 javaScript进阶面向对象ES6

  • 相关阅读:
    html5 保存图片到服务器本地
    html5 canvas分层
    webstorm配置scss自动编译路径
    微信开发测试号配置
    html5手机网站需要加的那些meta/link标签,html5 meta全解
    css去掉iPhone、iPad默认按钮样式
    如何激活webstorm 11
    min-height在安卓下不起作用
    基于字符串模式的路由路径的一些示例。
    nodeJS搭建本地服务器
  • 原文地址:https://www.cnblogs.com/luckyzs/p/13550036.html
Copyright © 2020-2023  润新知