JS原型与原型链的剖析

JavaScript中万物皆对象,但对象之间也是有区别的。分为函数对象和普通对象
普通对象和函数对象
凡是通过new Function创建的对象都是函数对象,其他都是普通对象(通常通过Object创建),可以通过typeof来判断。
由function创造出来的函数,比如
function f1(){};
typeof f1 //“function”

var f2 = function() {}
typeof f2 // “function”

var o1 = new f1();
typeof o1 //“object”

var o2 = {};
typeof o2 //“object”
可能有人会问,不是通过new Function创建的对象才是函数对象吗?注意下面这两种写法是一样的
function f1(){}; 等价于var f1 = new Function();
写了这么多,有些人可能不展示了,这跟原型有什么关系呢?
下面两句话很重要
1、每一个函数对象都有一个prototype属性,但是普通对象是没有的;
  prototype下面又有个construetor,指向这个函数。
2、每个对象都有一个名为_proto_的内部属性,指向它所对应的构造函数的原型对象,原型链基于_proto_;
普通对象
var o = {};
1、o的确没有prototype属性
  2、o是Object的实例
console.log(o.prototype); //undefined
console.log(o instanceof Object); //true
函数对象
function Fun(){};
var f1 = new Fun();
1、Fun是函数对象,f1还是普通对象
2、f1是Fun的实例
console.log(f1.prototype); //undefined
console.log(f1 instanceof Fun); //true

原型对象
说到原型对象,我们先了解下构造函数是什么?构造函数与其他函数唯一的区别在于调用方式不同。任何函数只要通过new来调用就可以作为构造函数,它是用来创建特定类型的对象。
下面定义一个构造函数Animal:
function Animal(name){
this.name = name;
this.species = ‘动物’;
}
通过new命令来生成一个Animal实例:
var cat = new Animal (“猫”)
这里,构造函数Animal就是实例对象cat的原型!!!Animal里的this关键字就指的是cat这个对象!
new出来的cat对象此时已经和Animal再无联系了!也就是说每一个new出来的实例都有自己的属性和方法的副本,是独立的的!修改其中一个不会影响另一个!
var dog = new Animal(“狗”);

dog.species= ‘食肉动物’;

console.log(cat.species) // 动物
console.log(dog.species) // 食肉动物

但是,我们希望构造函数中的species属性是一个共有属性,那么此时用这样的方法,每个实例中都有一个相同的species属性,会造成资源极大的浪费!
那么原型对象就即将登场了!给每一个构造函数都设置一个prototype属性,这个属性就指向原型对象。其实原型对象就只是个普通对象,里面存放着所有实例对象需要共享的属性和方法!所以,我们把需要共享的放到原型对象里,把那些不需要共享的属性和方法存在构造函数里!
那么上面的代码怎么修改呢?

function Animal (name){
this.name = name;
}
Animal.prototype.species= ‘动物’;

var cat = new Animal (“猫”);
var dog = new Animal(“狗”);
console.log(cat.species) // 动物
console.log(dog.species) // 动物

Animal.prototype.species = ‘食肉动物’;

console.log(cat.species) // 食肉动物
console.log(dog.species) // 食肉动物

可以看出,修改prototype属性会影响它的所有实例的species的值!!
实例一旦创建出来就会自动引用prototype对象的属性和方法!所以实例对象的属性和方法一般分为两种:一种是自身的,一种是引用自prototype的。
具体实现是这样的:
每当代码读取某个对象的某个属性的时候,都会执行一次搜索。首先从对象实例本身开始,如果在实例中找到了该属性,则返回该属性的值,如果没有找到,则顺着原型链指针向上,到原型对象中去找,如果找到就返回该属性值。
原型链
事实上,js里完全依靠"原型链"(prototype chain)模式来实现继承。
上面说完原型对象。下面要扒一扒__proto__、prototype、constructor
proto:事实上就是原型链指针!!
prototype:上面说到这个是指向原型对象的
constructor:每一个原型对象都包含一个指向构造函数的指针,就是constructor
继承实现方式:
为了实现继承,__proto__会指向上一层的原型对象,而上一层的结构依然类似,那么就利用__proto__一直指向Object的原型对象上!Object.prototype.proto = null;表示到达最顶端。如此形成了原型链继承。
下面有个图解非常经典,可以手画几遍去理解,非常有效~
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值