我的认知中关于原型(链)和this的错误

在Mozilla的mdn上关于Javascript是这样描述的

JavaScript 是一种基于原型的面向对象语言,而不是基于类的

所以指针的引用访问如果没有搞清楚,就很容易混淆其访问顺序,特别是当你的认识一支半截的时候(本文不会特别阐述原型链和作用域等问题,但会提及)。

回到原型上来!.

从ECMAScript的描述中我们得知,创建一个函数时会自动带有一个prototype的属性,该属性是指向函数原型对象的指针,每个原型对象都会有一个constructor属性(从传统的编程语言上,我们可以认为这个是该对象的构造函数,传统高级编程语言一般都需要显示的申明其构造函数)

当我们创建一个实例时,会自动带有一个__proto__的属性(可以理解为private),该属性指向其原型对象

Javascript中对象的prototype属性的解释是:返回对象类型原型的引用

所以每一个对象都有他的原型,这个原型有他自己的原型,直到最顶层的原生类型最后会返回(Null);那么在外部调用时,会首先去找自身属性,看其是否有,如果没有,就去找原型中是否有该属性,如果原型中没有,就会再往上层找原型的原型所具有的属性,找不到则返回undefined.

简单点来讲这就是原型链。举个例子:

假如你是一个10岁儿童,你要买糖,先摸下口袋里有没有钱,发现没有,就去找你老娘要,你老娘发现包里也没钱,让你去奶奶那里要要看。

如果你有呢?同时你老妈也有呢!你当然会先找自己包里的钱,因为你已经等不及要去买糖了(你真伟大,是我,就去老娘那里抠一点过来再说!) 。这种情况叫"属性遮盖"


当然,如果你对this理解不清楚,如果理解了上面的部分反而更容易犯错(挺纠结的,爱恨交织!)

放一段代码来看看

1 function Base() {
2   this.desc = "Javis";        
3 }
4 
5 Base.prototype.desc = "I'm not Jarvis! ";
6 
7 //xxoo
8 console.log(new Base().desc);

猜一猜再去检验!

之前我的认识this指向name是Base的静态属性,通过new 创建的实例本身不具有该属性,但是他的原型属性中定义了name的值。那么它应该是”I'm not Jarvis“

> Jarvis

哦。no!!! 那I'm not Jarvis被覆盖了。我靠?,找一找

> console.log(new Base().__proto__.desc);
> I'm not Jarvis

改下代码:

 1 function Base() {
 2   this.desc = "我是真的Jarvis";
 3 }
 4 Base.prototype = {
 5   desc: "我是Jarvis",
 6   addDesc: function(desc) {
 7     this.desc= desc;
 8   }  
 9 }
10 
11 var myInstance = new Base();
12 myInstance.addDesc("你是假的");
13 console.log(myInstance.desc);
14 console.log(Base.hasOwnProperty('desc'));

哦!false!Base没有该属性..this 指向的是上下文。

也许你到这里都是轻松过关。。那么如果把Base换成Object类型呢?

var Base = {
  desc: "我是真的Jarvis",
  updateDesc: function() {
    this.desc = "你是假的";
  }  
}
Base.updateDesc();
console.log(Base.desc);
console.log(Base.hasOwnProperty('desc'));

//想到答案了吗?哇靠这还不简单。

把this换成Base.

Base.desc = "你是假的";

答案也一样!

不行,不行我还得换一换!

var Base = {
  desc: "我是真的Jarvis",
  updateDesc: function() {
     this.desc = "你是假的"; 
  }
};

var Child = function () {
  this.desc = "哈哈,我是来看戏的!";
  this.updateDesc = function() {
    this.desc = "靠!越演越有爱了!";
  };
}

Child.prototype.updateDesc = Base.updateDesc;

var b = new Child();
console.log(b.desc);
b.updateDesc();
console.log(b.desc);

好了。到了这里属性遮盖也出现了。。

posted @ 2013-08-04 01:52  爵爷Jarvis  阅读(349)  评论(0)    收藏  举报