前置知识

JavaScript中一切皆对象。

  1. 除了undefined之外所有的数据类型都是对象(引用类型)或者有其对应的包装类(原始类型)。

    • 原始值(不可变)

      • undefined
      • null
      • Boolean
      • Number
      • String
      • Symbol (es6新增)
      • BigInt (es6新增)
    • 引用类型

      • Object
      • Array
      • Function
      • RegExp
      • Date
      • Promise (es6新增)
      • Map (es6新增)
      • Set (es6新增)
      • WeakSet (es6新增)
      • WeakMap (es6新增)
      • ...
//null也是对象
console.log(typeof null) //"object"
  1. 所有对象都有其对应的构造函数,null除外。

    可以理解为所有对象都是由函数产生的,都可以使用new关键字创建,函数也是一个对象,由Function产生。

    var num = new Number(); //数字
    var str = new String(); //字符串
    var bool = new Boolean(); //布尔值
    
    var obj = new Object(); //空对象
    //定义一个函数
    function sum(a, b){
        return a + b;
    }
    
    //相当于下面的写法
    var sum = new Function("a", "b", "return a + b");
    //自定义构造函数
    function Person(name, age){
        this.name = name;
        this.age = age;
    }
    
    var person = new Person('wlicox', 18); //自定义对象

new一个对象的时候JS做了哪些事情

  1. 隐式的创建一个this对象;
  2. this对象中包括一个prototype属性,指向该构造函数的原型;
  3. prototype对象中包括一个construtor属性,指向该构造函数本身;
  4. 返回this

用代码解释大概就是下面这样的:

假设有一个自定义构造函数Person

function Person(name, age){
    this.name = name;
    this.age = age;
}

var person = new Person('wlicox', 18);

当执行var person = new Person('wlicox', 18)时,

function Person(name, age){
    //1.隐式的创建一个this对象
    var this = {
        //2.this对象中有一个prototype属性
        prototype: {
            construtor: Person //3.构造函数指回Person自己
        }
    };

     /*用户代码*/
    this.name = name;
    this.age = age;

    return this; //4.隐式的返回this
}

构造函数和普通函数的区别

  1. 构造函数只做一件事,就是创建对象,普通函数可以提高编写的效率以及代码的复用等;
  2. 构造函数的命名使用大驼峰,普通函数的命名使用小驼峰;
  3. 构造函数的入参是作为创建对象的属性的值,普通对象的入参是用来提高函数的灵活性的;
  4. 构造函数使用new关键字调用,普通函数使用()调用;
  5. 构造函数不能有返回值,如果显式的返回一个引用类型的值,那么通过new创建的对象就是该返回值(返回原始类型的值不影响结果),普通函数有没有返回值都可以。
function Person(name, age){
    this.name = name;
    this.age = age;
    return {};
}

var person = new Person('wilcox', 18)
console.log(person) //{}

原型prototype

  1. 原型实际上就是一个普通的对象,每个构造函数创建的时候都有个自己的原型;
  2. 构造函数通过prototype属性找到它的原型;
  3. 构造函数创建的对象会继承其构造函数原型对象的属性;
  4. 只有函数才有prototype属性,对象没有。

构造函数construtor

原型对象中的属性,指向该构造函数本身;

Person === Person.prototype.constructor //true

隐式原型__proto__

用构造函数生成的对象可以使用__proto__属性找到其构造函数的原型;

//获取一个对象的原型的两种方法:
person.__proto__ === Person.prototype //true
Object.getPrototypeOf(person) === Person.prototype //true

prototypeconstrutor__proto__三者的关系

原型链

  1. 每个对象都有__proto__属性,由__proto__属性串联起来的的对象的集合就是原型链;
  2. 当一个对象在自己身上找不到要查找的属性时,就会顺着原型链往上找;

  1. Object的原型处于原型链的最顶端,其中有一个toSting方法,这也就是为什么所有的数据类型都自带toString方法;
  2. null没有原型;
  3. 完整原型图:

继承

圣杯模式,通过一个中间函数实现继承,修改子类原型不会影响到父类的原型。

function inherit(Target, Origin){
    function F() {};
    F.prototype = Origin.prototype;
    Target.prototype = new F();
    Target.prototype.constuctor = Target; //重置自己的构造函数
    Target.prototype.uber = Origin.prototype; //找到自己真正继承的类
}
03-05 17:07