原生JS基础知识(十一)

原生JS基础知识

我的github

原型

  • 定义 : 原型是function对象的一个属性 , 其值类型为对象 , 它定义了构造函数 new 出的所有对象的公共祖先 , 通过该构造函数产生的对象 , 可以继承该原型的属性和方法

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VXjHGY5m-1581835275380)(./原型.png)]

  • 构造函数通过访问其隐式属性 prototype可以查看原型

    function Person() {}
    Person.prototype // 原型
    
  • 利用原型的特点和属性 , 可以提取共有属性

    // before
    function Car(color, owner) {
      this.color = color;
      this.owner = owner;
      this.height = 1400;
      this.lang = 4900;
      this.carName = "BMW";
    }
    
    // after
    Car.prototype.height = 1400;
    Car.prototype.lang = 4900;
    Car.prototype.carName = "BMW";
    function Car(color, owner) {
      this.color = color;
      this.owner = owner;
    }
    
    // simplify
    Car.prototype = {
      height: 1400,
      lang: 4900,
      carName: "BMW",
    }
    function Car(color, owner) {
      this.color = color;
      this.owner = owner;
    }
    
  • 对象通过访问其隐式属性 __proto__可以查看该对象的原型

    var p = new Person();
    function Person() {
      // var this = Object.create(Person.prototype);
        ...
      // return this;
    }
    
  • 对象通过访问属性 constructor可以查看其构造函数

    function Person() {}
    var p = new Person();
    p.constructor; // p.__proto__.constructor ( 继承 )
    
  • __proto__指向的原型可手动更改 , 让对象"认贼作父"

    function Person() {}
    Person.prototype.name = '父';
    var p = new Person();
    console.log(p.name); // 通过__proto__访问p的原型上的name属性 , 打印结果为 : 父
    var obj = {
      name: '贼'
    }
    p.__proto__ = obj;
    console.log(p.name); // 贼
    
  • 对象的构造函数constructor可手动更改 , 让对象"认贼作父"

    function Wang() {}
    function Li() {}
    Wang.prototype = {
      constructor: Li
    }
    var xiaoWang = new Wang();
    console.log(xiaoWang.constructor); // function Li() {}
    

原型链

GrandFather.prototype.__proto__ === Object.prototype

GrandFather.prototype.lastName = 'liu';
function GrandFather() {}
var grandfather = new GrandFather();

Father.prototype = grandfather;
function Father() {}
var father = new Father();

Son.prototype = father;
function Son() {}
var son = new Son();

console.log(son.lastName); // 'liu'
  • Object.create(原型)

    • 原型必填 , 且为对象或null

    • Object.create(null)可创造出无原型的对象 , 故 Object.prototype是JS中绝大多数对象的最顶部原型而非全部 , 且手动增添属性 __proto__并无继承功效

      var obj = Object.create(null);
      obj.__proto__ = { name: 'father' };
      console.log(obj.name); // undefined
      
  • 原型链编程之重写方法

    f : Object.prototype.toString : 
        "[object Number]"
        "[object String]"
        "[object Boolean]"
        "[object Array]"
        "[object Object]"
    
    f : Number.prototype.toString
    f : String.prototype.toString
    f : Boolean.prototype.toString
    f : Array.prototype.toString
    
    var num = 123;
    num.toString(); // 先使用包装类包装成对象 , 然后依据原型链的就近访问原则调用Number.prototype.toString方法 , 返回 "123"
    Object.prototype.toString.call(123); // "[object Number]"
    
    • Tips : . 被识别成小数点的优先级高于被识别成访问属性/方法的符号 , 故 123.toString()会报错

    • Tips : document.write 方法会隐式调用 toString 方法再将结果打印在浏览器页面上

      // 验证
      var obj = Object.create(null); // 创建无原型对象( 也就无toString )
      obj.toString = function () { return 'haha' } // 手动添加 toString 方法
      document.write(obj); // 页面显示 'haha'
      

call / apply

  • 再看函数的执行

    function foo() {}
    foo(); // 真实面目为 ```foo.call()```
    
  • call改变this指向

    function Person(name) {
      this.name = name;
    }
    Person('liu'); // 此时函数Person中的this默认指向window
    var obj = {}
    Person.call(obj, 'liu'); // 此时函数Person中的this指向obj
    
  • call的高级用法 ( 借用别的方法实现自己的功能 )

    function Person(name, sex) {
      this.name = name;
      this.sex = sex;
    }
    
    // before
    function Student(name, sex, age, grade) {
      this.name = name;
      this.sex = sex;
      this.age = age;
      this.grade = grade;
    }
    var student = new Student('xiaoliu', 'male', 18, 'three');
    
    // after
    function Student(name, sex, age, grade) {
      Person.call(this, name, sex);
      this.age = age;
      this.grade = grade;
    }
    var student = new Student('xiaoliu', 'male', 18, 'three');
    
  • apply 和 call 都能改变this指向 , 但call逐个传递参数 , 而apply传递实参列表arguments

    function Person(name, age, sex) {}
    var obj = {}
    Person.call(obj, 'xiaoliu', 18, 'male');
    Person.apply(obj, ['xiaoliu', 18, 'male']);
    
发布了49 篇原创文章 · 获赞 29 · 访问量 1914

猜你喜欢

转载自blog.csdn.net/Brannua/article/details/104342476