JS高级【一】---原型链,继承

本文详细探讨了JavaScript中的原型链、继承机制,包括ES6类的继承、new操作符的本质、静态成员对象和原型对象的作用。通过实例解析了如何通过构造函数和原型对象实现继承,并介绍了ES5新增的Object.keys和Object.defineProperty方法。此外,还阐述了类的本质和原型链的工作原理,以及如何通过原型链实现方法的共享。

  • 面向过程就是一步步实现解决问题的步骤
    • 打开冰箱,放大象,关门
    • 不易维护,联系紧密
  • 面向对象是把事务分解为一个个的对象,然后对象间分工合作
    • 大象对象:进入
    • 冰箱对象:打开,关闭
    • 容易维护,复用,扩展,耦合度低
  • JS对象由属性方法构成
  • 对象是类的实例化

ES6类的继承

  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);  //作用是调用father构造器,如果不写这句话,son1.sum()会报错,因为其实x,y是写到Father里的,sum调用Father的属性
    }
  }

  var son1 = new Son(100, 200);
  son1.sum();// => 300

  • 继承中如果子类实例化输出方法,先看子类有没有,没有就看父类有没有,如果有就执行这个方法
  • 子类构造函数必须把super放在this前面
  • ES6中类没有变量提升,必须定义类才能实例化对象
  • 类的属性和方法一定要加this使用
  • constructor里面的this指向实例对象,方法里面的this指向这个方法的调用者
  • ES6前,对象不是基于类创建的,而是用一种称为构建函数的特殊函数来定义对象和他们的特征
// 利用对象字面量创建对象
var obj = {}

// 利用构造函数创建对象
function Person(age, name) {
    this.name = name;
    this.age = age;
    this.walk = function(){
        console.log("walk");
    }
}

var xiaoming = new Person('xiaoming', 18);
console.log(xiaoming);  // => Person {name: 18, age: "xiaoming", walk: ƒ}
xiaoming.walk(); // => walk
new的过程的本质
  • new构造函数的过程中做的4件事

    • 在内存中创造新的空对象
    • 让this指向这个新对象
    • 执行构造函数里面的代码,给这个新对象添加属性和方法
    • 返回这个新对象
静态成员对象
  • 静态成员:在构造函数本身添加的成员, 如Person.sex = '男'

    • 静态成员属于类不属于实例,实例中没有这个属性
  • 实例成员:构造函数通过this添加的成员,只能通过实例化的对象来访问

  • 构造函数浪费内存,不同对象同样的方法放在不同地址空间

    • 构造函数通过原型分配的函数是所有对象所共享的
    • 每个构造函数都有一个prototype对象
    • 把不变的方法直接定义在prototype对象上,所有的对象实例就可以共享这些方法
    • 原型就是prototype称为原型对象
    • 原型的作用是共享方法
    • Person.prototype.walk = function(){}
    • 对象身上系统自动添加__proto__(对象原型)指向我们构造函数的原型对象
      • xiaoming.__proto__ === Person.prototype // => true
  • 原型对象里面有constructor属性,很多情况下,我们需要手动利用constructor这个属性指回原来的构造函数

  •         function Person(age, name) {
              this.name = name;
              this.age = age;
              this.walk = function(){
                console.log("walk");
              }
            }
          	  console.log(Person.prototype.constructor);
            /*
            ƒ Person(age, name) {
              this.name = name;
              this.age = age;
              this.walk = function(){
                console.log("walk");
              }
            }
             */
    
  • 如果修改了原型对象,给原型对象赋值一个对象,要让constructor指回原来的构造函数constructor: Person

  • image-20201223131228794

原型链

  • 原型链:先在对象里找有没有成员,然后顺着原型链找原型对象里面有没有(原型对象.__proto__就可以找到原型对象指向的原型对象)

    • image-20201223131628438
    • 原型对象的函数里面的this指向的是实例对象
  • 扩展内置对象

    •   Array.prototype.sum = function () {
          var sum = 0;
          for(let i = 0; i < this.length; i++) {
            sum += this[i];
          }
          console.log(sum);
        }
        
        var arr = [1, 2, 3];
        arr.sum(); // => 6
      
  • call

    • 可以改变函数的this指向

    • var obj = {}
      
      function f(x, y) {
          console.log(this);
          console.log(x + y);
      }
      
      fn.call(obj, 1, 2); // obj  3 
      

ES5继承

  • 继承属性

    • ES5通过构造函数+原型对象实现继承,对于属性,通过call把父类的this指向子类的this就可以实现基础父类属性,对于方法,

    • function Father(name, age){
          this.name = name;
          this.age = age;
      }
      function Son(name, age, score){
          // new Son时 this指向son,再把Father this指向改成son
          Father.call(this, name, age);
          this.score = score;
      }
      
      var son = new Son('xiaoming', 16, 88);
      console.log(son); //=> Son {name: "xiaoming", age: 16, score: 88}
      
  • 继承方法

    •      function Father(name, age) {
             this.name = name;
             this.age = age;
           }
           Father.prototype.money = function () {
             console.log(100);
           }
         
           function Son(name, age, score) {
             Father.call(this, name, age);
             this.score = score;
           }
         
           Son.prototype = new Father();
           Son.prototype.constructor = Son;
           Son.prototype.exam = function () {
             console.log("要考试");
           }
         
           var son = new Son('xiaohua', 18, 100);
      
    • image-20201223211809493

ES6类的本质

  • 类的本质还是一个函数,可以认为类是构造函数的另一种写法
  • 类有原型对象
  • 类原型对象的constructor指向类本身
  • 类可以通过原型对象添加方法
  • 类创建的实例对象有__proto__原型指向类的原型对象
  • 可以认为类是语法糖

ES5新增函数

// foreach 遍历数组

var arr = [1, 2, 3]
arr.foreach(function(value, index, array) {
    console.log(value);  // 每个数组元素  => 1 2 3
    console.log(index);  // 每个数组元素的索引号 => 0 1 2
    console.log(array)   // 数组本身 => [1,2,3] [1,2,3] [1,2,3]
})

// filter 筛选数组
var arr = [12, 66, 4, 88]
var newArr = arr.filter(function(value, index) {
    return value > 20;
})
console.log(newArr); //=> [66, 88] 

// some 查找数组中是否有满足条件的元素
// 如果找到第一个满足的元素就终止循环退出
var arr = [10, 30, 4]
var flag = arr.some(function(value) {
    return value < 3;
})
console.log(flag) // => false

//foreach里面用return不会终止查找,但是some会

//trim 去除字符串两边的空格
var str = ' an dy '
var str1 = str.trim();
console.log(str1) // => 'an dy'
Object.keys
  • 获取对象自身所有属性
        var obj = {
            id: 1,
            pname: '小米',
            price: 1999,
            num: 2000
        };
        var arr = Object.keys(obj);
        console.log(arr); // => ["id", "pname", "price", "num"]
Object.definePropety

object.definePropety() 定义新属性或修改原来的属性

Object.definePropety(obj, prop, descriptor)

Object.definePropety() 第三个参数descriptor说明:对象,以{}形式书写

  • value:设置属性的值,可以为undefined
  • writable: 值是否可以重写,true|false ,false 默认
  • enumerable:目标属性是否可以被枚举,true|false false默认
  • configurable: 目标属性是否可以删除或是否可以再次修改特性 true|false 默认为false
Object.defineProperty(obj, 'address', {
            value: 'myAddress',
            // 如果只为false 不允许修改这个属性值 默认值也是false
            writable: false,
            // enumerable 如果值为false 则不允许遍历, 默认的值是 false
            enumerable: false,
            // configurable 如果为false 则不允许删除这个属性 不允许在修改第三个参数里面的特性 默认为false
            configurable: false
        });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值