浅谈Javascript里构造函数,以及prototype和__proto__

一、探讨

var F = function(){};
Object.prototype.a = function(){};
Function.prototype.b = function(){};
var f = new F();

问:能否通过f取到方法a,方法b?

这是在别人文章里看到的问题,希望看了文章之后大家能给出解答

在最后我会给出解答,现在让我们开始吧

二、先理解下下列几项描述

  1. 所有函数都可以当作构造函数来使用
  2. 所有实例都有其构造函数,比如Number,String,Array,Object。。。。。

三、构造函数

先看个简单例子

function People(name,age){//构造函数
	this.name=name;
	this.age=age;
}

let zhangsan=new People("张三","18");//实例

console.log(zhangsan.constructor);//返回该实例的构造函数function People(){}

这里有个问题,为何zhangsan.constructor返回其构造函数?这里就要说到原型属性prototype

三、函数的原型属性——prototype

对于任何一个构造函数来讲,都有一个 属性 prototype,这个属性几个特点

  1. 它是一个对象
  2. 构造函数生成的所有实例都共享其原型属性prototype里的属性和方法
  3. prototype里有一个属性constructor,返回原函数

再来看一个例子:

function People(){};//写一个构造函数

People.prototype.say=function(){//添加一个原型方法
	console.log("我们都是一家人")
}
People.prototype.blood="red";//添加一个原型属性
console.log(People.prototype);//输出该构造函数的原型对象

let zhangsan=new People();//生成一个实例
zhangsan.say();//输出:"我们都是一家人"

我们来看一下控制台输出内容

People.prototype是个对象,它有四个属性:blood、say、constructor、__proto__,blood和say是我们添加的原型属性,而constructor:f People(),它返回的是原构造函数。上面我们讲到了实例共享其原型属性prototype里的属性和方法,自然也共享了这个constructor,所以zhangsan.constructor返回其构造函数。至于__proto__我们下面讲到,

四、隐式原型——__proto__

__proto__表示其构造函数的原型属性,因为所有的实例都有构造函数,所以所有的实例都有__proto__属性。我们再来看个实例:

function People(){};//写一个构造函数
let zhangsan=new People();//生成一个实例
//zhangsan.__proto__==zhangsan.constructor.prototype==People.prototype;
console.log(zhangsan.__proto__==People.prototype);//返回true
console.log(zhangsan.__proto__==zhangsan.constructor.prototype);//返回true

__proto__的属性已经讲到了,有人可能问,zhangsan.__proto__表示People构造函数的原型属性,那么zhangsan.__proto__.constructor应该返回的是该构造函数People,而上面讲到了zhangsan这个实例共享构造函数里的属性和方法,那么我们再看一下上个实例输出的图片,输出的是People.prototype,因为共享,zhangsan.__proto__.constructor应该指向红箭头标的,即Object的构造函数,但为何指向的是People这个构造函数?因为People.prototype本质上是一个对象,对象的隐式原型的constructor自然指向Object的构造函数,zhangsan这个实例的__proto__重写了People.prototype里的__proto__

五、对开头问题的解答

var F = function(){};
Object.prototype.a = function(){console.log("我是a")};
Function.prototype.b = function(){console.log("我是b")};
var f = new F();

由f实例如何找到a和b?

首先来看a,我们先找个Object对象,在找其原型,我们可以通过f.__proto__得出F.prototype这个对象,因为是个对象,所以f.__proto__.__proto__得到Object.prototype

再来看b,先找个Function,即f.constructor,所以f.constructor.__proto__得到Function.prototype

所以 f共享f.__proto__里的内容,f.__proto__共享f.__proto__.__proto__里的内容

而f.constructor共享f.constructor.__proto__里的内容

即:

var F = function(){};
Object.prototype.a = function(){console.log("我是a")};
Function.prototype.b = function(){console.log("我是b")};
var f = new F();

f.a();//输出 :我是a
f.constructor.b();//输出 :我是b

f.__proto__.__proto__.a=function(){console.log("我是a2")};
f.a();//输出:我是a2

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值