【js重学系列】原型

初始

  1. JavaScript 中,万物皆对象!
  2. 但对象也是有区别的。分为普通对象和函数对象,像Object ,Function 是JS自带的函数对象
  3. 怎么区分?其实很简单,凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。
  4. Function Object 也都是通过 New Function()创建的。

构造函数

  1. 构造函数可用来创建特定类型的对象。像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境中。

  2. function Person() {
    
    }
    var person = new Person();
    person.name = 'Kevin';
    console.log(person.name) // Kevin
    
  3. 按照国际惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头。

  4. 要创建Person的新实例,必须使用new操作符。一般是经历以下四个步骤:

    1. 创建一个空对象(即{});
    2. 设置原型链(将实例对象的原型对象,指向构造函数的原型对象)
    3. 新创建的对象作为this的上下文 ,只改this指向并且把参数传递过去
    4. 如果是值类型,返回obj。如果是引用类型,就返回这个引用类型的对象

原型

  1. 无论什么时候,只要创建一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。普通对象没有 prototype,但有 __proto__ 属性。

  2. 如上面例子,Person.prototype 指向了原型象,而 Person.prototype.constructor 又指回了Person。

  3. 而 person 只是一个对象实例。

  4. 而person可以访问保存在原型中的值,但却不能重写原型中的值。如果我们在 person 中添加一个属性,而该属性与实例原型中的一个属性同名,那个person中的属性会暂时屏蔽原型中的属性,删除后,还是读回原型中的属性

  5. function Person() {
    
    }
    Person.prototype.name = 'Perty';
    var person = new Person();
    person.name = 'Kevin';
    console.log(person.name) // Kevin
    delete person.name
    console.log(person.name) // Perty
    
    解析器的操作是:
    
    “实例person有name属性吗?”
    “有” —— 于是就读取实例中的name属性,输出 Kevin
    
    删除后,再运行时:
    
    “实例person有name属性吗?”
    “没有”
    “person的原型有name属性吗?”
    “有” —— 于是就读取原型中的name的属性,输出 Perty
    
  6. ①所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象
    ②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象
    ③所有引用类型的__proto__属性指向构造函数的prototype

  7. var a = [1,2,3];
    a.__proto__ === Array.prototype; // true
    

原型链

  1. 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做 __proto__ 的内置属性,用于指向创建它的函数对象的原型对象 prototype。以上面的例子为例:

  2. console.log(person.__proto__ === Person.prototype)  *// true*
    
  3. 同样的,Person.prototype 也同样有 proto 属性,它指向创建它的函数对象(Object)的prototype

  4. console.log(Person.prototype.__proto__ === Object.prototype) *// true*
    
  5. 继续,Object.prototype对象也有__proto__属性,但它比较特殊,为nul

  6. console.log(Object.prototype.__proto__) *// null*
    
  7. 我们把这个有 __proto__ 串起来的直到 Object.prototype.__proto__ 为null的链叫做原型链。

  8. person.__proto__ ==> Person.prototype.__proto__ ==> Object.prototype.__proto__ ==> null
    
  9. 当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链

  10. function Parent(month){
        this.month = month;
    }
    
    var child = new Parent('Ann');
    
    console.log(child.month); // Ann
    
    console.log(child.father); // undefined
    
  11. 在child中查找某个属性时,会执行下面步骤

  12. ①一直往上层查找,直到到null还没有找到,则返回undefined
    Object.prototype.__proto__ === null
    ③所有从原型或更高级原型中的得到、执行的方法,其中的this在执行时,指向当前这个触发事件执行的对象

链接:

https://blog.csdn.net/xiaoermingn/article/details/80745117
https://juejin.cn/post/6844903540943503367
https://www.jianshu.com/p/ddaa5179cda6
https://www.jianshu.com/p/dee9f8b14771

原文地址:https://www.cnblogs.com/ycyc123/p/14322659.html