__proto__与prototype

值得一说的是对象没有prototype属性,只有函数有prototype属性。

var a = function(){};
a.prototype.d = function(){
    console.log(1);
}

prototype相当于给函数a添加了一个属性。

var a = function(){};
a.prototype.d = function(){
    console.log(1);
}

var b = new a();
b.d(); //1

用prototype添加的属性,实例化后这个函数的对象也可以继承这个属性。

那为什么要用prototype添加属性呢?来看看

var a = function(){
    var f = function(){
        console.log(2);
    }
};

var b = new a();
b.f(); //报错

  为什么报错?先看一下call方法和new对象的关系这篇文章,看完你就明白b可以继承函数a的prototype属性了。

  注意我那篇文章只说的了new可以继承prototype属性,但是没有说它可以继承函数里面的内容。所以为什么解决这个为什么我们就会用到prototype了,当然有时为了一些优化的原因也会这样用。

  其实不只是prototype可以解决这个问题,还有this也是可以解决这个问题的,就像我们使用构造函数一样,我们都是用的this对吧,因为new以后就会改变这个this的指向,然后这个属性就会变成你创建出来的那个对象的属性。  对于this的指向问题可以看彻底理解js中this的指向,不必硬背。

function Fn(){
    this.num = 10;
}
var a = new Fn();
console.log(a.num); //10

  那么__proto__是什么?为了更好的理解__proto__建议你先看什么是作用域链这篇文章。

  __proto__和作用域的行为类似,只不过__proto__是对于对象的属性来说的,而作用域链是对于变量来说的,什么意思?就是说一个对象如果要打印这个对象的某个属性,那么它会先在自己的对象中查找,如果没有找到那么它就会__proto__中找,看看有没有这个属性。那么__proto__中到底有哪些属性?

  你一开始创建的对象__proto__指向了obj.__proto__,也就说明我们创建的任何对象都可以调用obj.__proto__里面的属性和方法,而obj的__proto__为null,也就是说到obj的__proto__就到头了。这也就是说如果我们没有做任何的操作,这个对象只能继承obj.__proto__的属性,这里没有算上obj的__proto__是因为,obj的__proto__为null。

  但是如果我们用了new操作符实例化了一个函数,那么这个new出来的对象就又多了一个继承对象,那就是那个构造函数。而这个构造函数如果用prototype添加属性同样的,这个实例化的对象也可以继承它的属性。

  还有一点就是如果这个对象本身就有这个属性就不会去继承,继承只有在这个对象没有找到的时候才会继承,就和我们学css的继承样式一样。

function Fn(){
    
}
Fn.prototype.num = 10;
var a = new Fn();
a.num = 20;
console.log(a.num); //20

如果这个对象没有这个属性才会继承,并且这个对象有多个__proto__那么它也只是继承最近的那个属性。

function Fn(){
    
}
Fn.prototype.num = 10;
var a = new Fn();
console.log(a.num);

在这段代码中Fn的__proto__离对象a最近所以继承它的,而不是obj的。

补充一点:

function Foo() {};
var foo = new Foo();
Foo.prototype.num = 52;
console.log(foo.num); //52
console.log(Foo.num); //undefined

再看

function Foo() {};
var foo = new Foo();
Foo.prototype.num = 52;
console.log(foo.num); //52
console.log(Foo.prototype.num); //52

对,你没有猜错,num只是prototype的属性,而prototype是Foo的属性,自然只能通过Foo.prototype.num来访问这个属性,那么为什么new出来的对象可以不用加prototype就可以访问num呢?

实际上new出来的对象是这样的。

var fn = function(a){
    this.a = a;
}
var obj = {};
继承
obj.__proto__ = fn.prototype;
改变this指向
fn.call(obj);

看到没有,已经写了fn.prototype,自然就可以在后面点那个属性了。ok了吧?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值