前端JavaScript

原型 && 原型链

2020-03-25  本文已影响0人  晚月川

原型 && 原型链

  1. arr1.length 或者 arr1[0] =>获取当前实例的私有属性值
  2. arr1.push()
    • 首先找自己的私有属性,私有属性有,调取的就是私有属性;如果没有,默认基于__proto__原型链属性,找所属类prototype原型上的公共属性和方法;如果还没有则基于原型prototype中的__proto__继续向上查找,一直找到Object.prototype为止
  3. arr.__proto__.push
    • 直接找所属类原型上的push方法,类似于Array.prototype.push这样找arr1.__proto__.push === arr2.push === Array.prototype.push

原型链查找机制:基于实例__proto__找所属类的prototype
=>实例的私有属性方法
=>实例的公有属性和方法

push是arr1实例的“公有属性方法” pushArray.prototype的私有属性
hasOwnProperty是arr1实例的“公有属性方法”
对象的私有属性:存储在自己的堆中,无需基于__proto__查找
对象的公有属性:自己堆中没有,需要基于proto找prototype上的

Array.prototype.hasOwnProperty('hasOwnProperty'); //=> false
Object.prototype.hasOwnProperty('hasOwnProperty'); //=> ture

所有对象都是Object的实例:只要原型链最后都能找到Object.prototype,那么都是对象类的一个实例(也就是对象),例如:数组是Array的一个实例,但是最后原型链也找到了Object.prototype,所以数组也是对象类的一个实例(也是一个对象)

document -> HTMLDocument.prototype -> Document.prototype -> Node.prototype -> EventTarget.prototype -> Object.prototype
每个元素对象 最后都能找到 Object.prototype,所以它们也是对象类的实例,也是一个对象
元素集合 -> HTMLCollection.prtotype -> Object.prototype

只要在当前实例原型链上的属性和方法 实例都可以调用
JS中的所有值,最后基于原型链,都能找到Object.protitype原型,也就是都是对象类的实例,也就是都是对象 =>(万物皆对象)

/*  向类的原型上扩展属性方法
    Fn.prototype.xxx = xxx; 向默认的堆内存中增加属性方法
    =>如果需要设置很多属性方法,操作起来比较麻烦(小技巧:给Fn.prototype设置别名) */
let prop = Fn.prototype;
prot.A = 100;
prot.B = 200; 
prot.C = 300;
// 这类方式的特点都是向默认开辟的堆内存中扩展属性和方法,默认开辟的堆内存中存在constructor这个属性
// 重定向Fn的原型指向
// =>自己开辟的堆内存中是没有constructor这个属性的,所以真实项目中,为了保证结构的严谨性,我们需要手动设置constructor
// =>如果在重定向之前,我们向默认开辟的堆内存中设置了一些属性方法,重定向后,之前设置的属性方法都丢失了(没用了)
Fn.prototype = {
    constructor:Fn;
    xxx:xxx
}


JS中有很多内置类,而且在内置类的原型上有很多内置的属性和方法
Array.prototype:数组作为Array的实例,就可以调取原型上的公共属性方法,完成数组的相关操作 => arr.push():arr基于proto原型链的查找机制,找到Array.prototype上的push方法,然后把push方法执行,push方法执行:
=> 方法中的this是arr这个数组的实例
=> 作用向arr(也就是this)的末尾追加新的值
=> 返回结果是新增后数组的长度

// 向内置类原型扩展方法:
// Array.prototype.xxx = xxx;
// =>这种方法存在风险:我们自己设置的属性名可能会把内置的属性给覆盖掉
// =>一般我们自己在内置类原型上扩展的方法,设置的属性名做好加上前缀
Array.prototype.push = function () {
    console.log('自己的push');
};
let arr = [10,20];
arr.push(100);
// 浏览器为了保护内置类原型上的方法,不允许我们重新定向内置类原型的指向(严格模式下会报错)
Array.prototype = {
    AA:100
};
/* 
 * 模拟内置的push方法
 *  在类的原型上编写的方法,让方法执行,我们一般都这样操作:实例.方法(),所以方法中的this一般都是我们要操作的这个实例,我们基于this操作就是操作这个实例
 */
Array.prototype.push = function puah(value) {
    // this:要操作的数组实例
    this[this.length] = value;
    return this.length;
};
let arr = [10,20];
console.log(arr.push(100),arr);
上一篇 下一篇

猜你喜欢

热点阅读