欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

带你理解JavaScript 原型原型链

程序员文章站 2022-03-28 20:25:03
目录看完这篇文章,你会发现,原型、原型链原来如此简单! 上面经典的原型链相等图,根据下文的学习,你会轻易掌握。一、原型、原型链相等关系理解首先我们要清楚明白两个概念:js分为函数对象和普通对象,每个对...

看完这篇文章,你会发现,原型、原型链原来如此简单!  上面经典的原型链相等图,根据下文的学习,你会轻易掌握。

一、原型、原型链相等关系理解

首先我们要清楚明白两个概念:

js分为函数对象和普通对象,每个对象都有__proto__属性,但是只有函数对象才有prototype属性
objectfunction都是js内置的函数, 类似的还有我们常用到的arrayregexpdatebooleannumberstring

这两个概念大家跟我一起读三遍并记住,后面会用到

那么__proto__prototype到底是什么,两个概念理解它们

  • 属性__proto__是一个对象,它有两个属性,constructor__proto__
  • 原型对象prototype有一个默认的constructor属性,用于记录实例是由哪个构造函数创建;

这两个概念大家跟我一起读三遍并记住,后面会用到

有以下构造函数person,他的原型上有所属国属性motherland='china'

 function person(name, age){ 
    this.name = name;
    this.age = age;
 }
 
 person.prototype.motherland = 'china'

通过new person()创建的person01实例

 let person01 = new person('小明', 18);

js之父在设计js原型、原型链的时候遵从以下两个准则

 person.prototype.constructor == person // **准则1:原型对象(即person.prototype)的constructor指向构造函数本身**
 person01.__proto__ == person.prototype // **准则2:实例(即person01)的__proto__和原型对象指向同一个地方**

这两个准则大家跟我一起读三遍并记住,后面会用到

记住以上四个概念两个准则,任何原型链相等判断都能判断正确;

大家可以对照上图,看看自己概念准则是否弄清楚了,一定要对照上图哦

// 从上方 function foo() 开始分析这一张经典之图
function foo()
let f1 = new foo();
let f2 = new foo();

f1.__proto__ = foo.prototype; // 准则2
f2.__proto__ = foo.prototype; // 准则2
foo.prototype.__proto__ = object.prototype; // 准则2 (foo.prototype本质也是普通对象,可适用准则2)
object.prototype.__proto__ = null; // 原型链到此停止
foo.prototype.constructor = foo; // 准则1
foo.__proto__ = function.prototype; // 准则2
function.prototype.__proto__  = object.prototype; //  准则2 (function.prototype本质也是普通对象,可适用准则2)
object.prototype.__proto__ = null; // 原型链到此停止
// **此处注意foo 和 function的区别, foo是 function的实例**

// 从中间 function object()开始分析这一张经典之图
function object()
let o1 = new  object();
let o2 = new  object();

o1.__proto__ = object.prototype; // 准则2
o2.__proto__ = object.prototype; // 准则2
object.prototype.__proto__ = null; // 原型链到此停止
object.prototype.constructor = object; // 准则1
object.__proto__ = function.prototype // 准则2 (object本质也是函数);
// 此处有点绕,object本质是函数,function本质是对象
function.prototype.__proto__ =  object.prototype; // 准则2 (function.prototype本质也是普通对象,可适用准则2)
object.prototype.__proto__ = null; // 原型链到此停止

// 从下方 function function()开始分析这一张经典之图
function function()
function.__proto__ = function.prototype // 准则2
function.prototype.constructor = function; // 准则1



由此可以得出结论: 除了object的原型对象(object.prototype)的__proto__指向null,其他内置函数对象的原型对象(例如:array.prototype)和自定义构造函数的 __proto__都指向object.prototype, 因为原型对象本身是普通对象。 即:

object.prototype.__proto__ = null;
array.prototype.__proto__ = object.prototype;
foo.prototype.__proto__  = object.prototype;

二:原型、原型链的意思何在

理解了这些相等关系之后,我们思考,原型、原型链的意思何在?原型对象的作用,是用来存放实例*有的那部份属性、方法,可以大大减少内存消耗。

用我们文章开始的person构造函数和person01实例举例说:

console.log(person01)


打印person01, 他有自己属性 name = '小明',age = 18; 同时通过原型链关系,他有属性motherland = 'china';

我们再创建person2实例

let person02 = new person('小花', 20);
console.log(person02)

打印person02, 他有自己属性 name = '小花',age = 20; 同时通过原型链关系,他有属性motherland = 'china'; 看出来了没有,原型对象存放了person01person02共有的属性所属国motherland = 'china'. 我们不用在每个实例上添加motherland 属性,而是将这一属性存在他们的构造函数原型对象上,对于人类person这样的构造函数。相同的属性、方法还有很多很多,比如我们是黑头发,我们都有吃,睡这样一个方法,当相同的属性、方法越多,原型、原型链的意义越大。 那我们可以这样操作

person.prototype.haircolor = 'black';
person.prototype.eat = function(){
    console.log('we usually eat three meals a day.')
}
console.log(person01)
console.log(person02)

此时我们再打印person01person02,我们惊喜的发现,他们有了属性haircoloreat方法;实例们动态的获得了person构造函数之后添加的属性、方法,这是就是原型、原型链的意义所在!可以动态获取,可以节省内存。

另外我们还要注意:如果person01将头发染成了黄色,那么haircolor会是什么呢?

person01,haircolor = 'yellow';
console.log(person01)
console.log(person02)

可以看到,person01haircolor = 'yellow', 而person02haircolor = 'black'; 实例对象重写原型上继承的属相、方法,相当于“属性覆盖、属性屏蔽”,这一操作不会改变原型上的属性、方法,自然也不会改变由统一构造函数创建的其他实例,只有修改原型对象上的属性、方法,才能改变其他实例通过原型链获得的属性、方法。

到此这篇关于带你了解js 原型原型链的文章就介绍到这了,更多相关js 原型原型链内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!