【JavaScript】原型链

构造函数

        - 本质还是一个函数
        - 和 new 关键字连用
        - 特点
                            1. 自动创建一个对象
                            2. 自动返回一个对象
                            3. 让函数的this指向这个对象 

        书写构造函数的时候
                            1. 属性写在函数内
                            2. 方法写在原型上

构造函数的不合理
把方法写在构造函数内的时候,随着实例增加,会额外创建很多一样的方法

原型

        💡  每一个 函数天生自带一个属性 prototype, 是一个对象
        💡   每一个 对象天生自带一个属性 __proto__, 指向所属的构造函数的原型 prototype

对象访问机制

            当访问一个对象的成员的时候,首先会在自己身上找
            如果没有,会自动找到自己的__proto__

原型 prototype
把公共的方法提取出来,在原型上书写,只用书写和创建一次
在JS中有若干内置构造函数
Object
Array
Date
RegExp
Function

function Person() { }

    // p1是一个实例对象, 是Person的实例对象
    // p1所属的构造函数 Person
    // p1的 __proto__ 指向 Person.prototype
    const p1 = new Person()
    console.log(p1.__proto__ === Person.prototype);

  /* 
      p1是一个实例化对象,Person是一个构造函数,p1所属的构造函数是Person 
      p1是一个对象,天生自带__proto__,所以p1.__proto__是小袋鼠的家也就等同于袋鼠妈妈的口袋.所以p1.__proto__是指向所属构造函数原型也就是Person.prototype,指向的意思是相等
      */

// 举一反三
			// 任何一个数组, 所属的构造函数是 Array
      // 任何一个对象, 所诉的构造函数是 Object

      function Array() {}
      function Object() {}
      let arr = new Array();
      let obj = new Object();
    	//都是全等的
      console.log(arr.__proto__ === Array.prototype);
      console.log(obj.__proto__ === Object.prototype);

内置构造函数

扩展方法
在内置构造函数的原型上扩展一个新方法, 所有的数组都可以使用这个方法
案例1: 给Array上的原型扩展一个方法, 返回数组里面的最大值

// 需求, 扩展一个方法, 返回数组里面的最大值
      Array.prototype.getMax = function () {
        // let max = Math.max(...arr);
        let max = Math.max(...this); //this指向arr
        return max;
      };

      let arr = [1, 2, 2, 2, 3, 400, 200, 300];
      console.log(arr.getMax());

案例2: 给Array上的原型扩展一个方法, 给数组去重

// 需求 扩展一个方法, 给数组去重
Array.prototype.noRepeat = function () {
  let newArr = [];
  arr.forEach((item) => {
    if (newArr.indexOf(item) == -1) {
      newArr.push(item);
    }
  });
  return newArr;
};


let arr = [1, 2, 2, 2, 3, 400, 200, 300];
console.log(arr.noRepeat());

现在我们来解决: 把公共的方法提取出来,在原型上书写,只用书写和创建一次, 这样所有的对象都可以使用

//使用内置构造函数原型创建新方法
Object.prototype.sing = function () {
  console.log("唱跳rap");
};

function Teacher() {}
// 之前的思路是直接给构造函数单独创建一个方法
// Teacher.prototype.sing = function () {
//         console.log("唱跳rap");
//       };

function Student() {}
// 之前的思路
// Student.prototype.sing = function () {
//         console.log("唱跳rap");
//       };

let t1 = new Object();
let s1 = new Object();

t1.sing();
s1.sing();
console.log(t1.sing());//这里打印会有undefined是因为打印的是函数的返回值,函数没有return
console.log(s1.sing());

小结: 之前的思路是直接给构造函数单独创建一个方法,这样每个构造函数都需要创建一个相同的方法会很麻烦,所以我们直接给内置的构造函数扩展一个方法,这样所有的对象都可以直接使用

一切皆对象

    对象
        - 一种数据结构  {name: 'tom' ,age : 18}
        - 一类内容中的一个真实个例
             属的构造函数就是Array
                     只要是 {} 所属的构造函数就是Object
                     只要是 function () {} 所属的构造函数就是Function

原型链

问题1 p.__proto__指向

function Person() {}
const p = new Person();
/* 
      问题1  p.__proto__指向
      每一个对象的__proto__指向所属构造函数的原型Person.prototype
       */
console.log(p.__proto__ === Person.prototype);
// console.log(typeof Person.prototype); //对象数据类型

问题2 Person.prototype.proto 指向哪里

function Person() {}
const p = new Person();
  /* 
      问题2 Person.prototype.__proto__ 指向哪里
      分析:
      1.这里将Person.prototype看做一个整体 是一个对象数据类型(原型概念)
      2.Person.prototype.__proto__ 指向所属构造函数的原型
      3.所属的构造函数是一个对象,所以指向Object.prototype
      */
      console.log(Person.prototype.__proto__ === Object.prototype);

问题3 Person.proto 指向哪里

function Person() {}
const p = new Person();
 /* 
      问题3 Person.__proto__ 指向哪里
      分析:
      1.Person.__proto__ 指向所属构造函数的原型
      2.所属构造函数是一个函数,所以指向Funciton.prototype
      */
      console.log(Person.__proto__ === Function.prototype);


问题4 Function.proto 指向哪里

function Person() {}
const p = new Person();
 /* 
     问题4 Function.__proto__ 指向哪里
      分析:
      1.Function.__proto__ 指向所属构造函数的原型
      2.所属构造函数是谁?  由于Function本身是一个构造函数,所以指向Function,这个比较特殊
      */
      console.log(Function.__proto__ === Function.prototype);
      


问题5 Object.proto 指向哪里

function Person() {}
const p = new Person();
 /* 
     问题5 Object.__proto__ 指向哪里
      分析:
      1.Object.__proto__ 指向所属构造函数的原型
      2.Object是一个内置构造函数,所以指向Function
      */
      console.log(Object.__proto__ === Function.prototype);


问题6 Function.prototype.proto 指向哪里

function Person() {}
const p = new Person();
  /* 
     问题6 Function.prototype.__proto__ 指向哪里
      分析:
      1.Function.prototype.__proto__指向所属构造函数的原型
      2.Function.prototype所属构造函数是Object
      */
      console.log(Function.prototype.__proto__ === Object.prototype);


问题7 Object.prototype.proto 指向哪里

function Person() {}
const p = new Person();
  /* 
     问题7 Object.prototype.__proto__ 指向哪里
     分析:
     1.Object.prototype 是顶级原型
     2.Object.prototype.__proto__ 指向null
      */
      console.log(Object.prototype.__proto__ === null);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芒果Cake

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值