javaScript原型模式中变量的查找

 function Person(){
 }
 Person.prototype.age=7;
 Person.prototype.getAge=function(){
    return age;
 }
 //调用函数
 var person=new Person();
 alert(person.getAge());
 

在调用person.getAge()后,会沿着作用域链查找该getAge()方法,首先会在new Person()对象中查找,没有找到;然后进入下一个作用域链对象,此时的对象为Person.prototype,而该对象中有getAge()方法,执行该方法后,由于目前作用域链的前端对象是Person.prototype,要返回age的值,该age值的查找得从原型对象Person.prototype中进行查找,此时原型对象中的age=7;那么调用函数应该返回的age也为7,也就是说,person.getAge()返回为7,但是,最后出现了错误:
Uncaught ReferenceError: age is not defined

各位大神,为啥会报错啊??

阅读 3.8k
5 个回答

你在getAge函数里面返回的是全局的age,因为你在这个函数里没有定义局部age,那么浏览器就会往全局变量里面找age,但是你全局变量里面也没有age,所以就像一楼说得要用this.age,这时候才是调用当前对象的age属性。

在JavaScript中,只有全局作用域和函数作用域(eval作用域除外)。单纯的大括号是无法形成作用域的。

你的例子可以改成成这样

function Person(){}

// 这里并不能形成作用域
Person.prototype = {
    age: 7,
    getAge: function() {
        return age;
    }
}

var person=new Person();
alert(person.getAge());
 

因为Person.prototype = {}不能形成作用域,所以你的整个理解都是错的。

函数getAge的上一级作用域就直接是全局作用域了。

person实例之所以能访问到原型上的getAge方法,是通过原型链找到的,而不是作用域。

首先,var person = new Person();生成了一个对象,该对象的作用域是window(在你的例子里面),然后,调用该对象的person.getAge()函数(这时用到的是原型链查找),需要打印age变量。那么,这时,JS引擎会在该对象的作用域内,一层层向上查找age变量(对象的作用域,就是声明该对象的位置)。

可见,window下并没有age变量,所以报错ReferenceError

如果把代码稍微修改一下,更能体现出作用域查找的效果:

var age = 123;
function test() {
    var age = 456;

    function Person() {
    }

    Person.prototype.age = 7;
    Person.prototype.getAge = function () {
        return age;
    };
    //调用函数
    var person = new Person();
    console.log(person.getAge()); //输出为456
}
test();

按照楼上的提示,如果修改为return this.age;,那么,查找顺序如下:

  1. 首先,在person作用域上查找this属性,我们知道,new Person()之后,person对象会自动绑定到this上,也就是说,this就是person

  2. 找到this之后,在查找该对象上的age属性,那么,根据原型链查找规则,自然,会找到Person.prototype.age = 7

  3. 最后,返回 7

改成

Person.prototype.getAge=function(){
    return this.age;
 }

不然找的是全局变量 age 不存在

你要记住下面这句话,至关重要,理解了这句话基本上就可以理解了
javascript规定,每个构造函数都有一个prototype属性,它会指向另一个对象,这个对象的所有属性和方法都可以被这个函数的实例调用。
function Person(){} 这句话是定义一个Person的构造函数,所以它有prototype属性
Person.prototype.age=7;
Person.prototype.getAge=function(){

return age;

}
这两句是定义它的属性和方法,Person.prototype可以把它看成一个对象,getName返回的是这个对象的age,要加个this,表示返回这个对象的age属性。
var person=new Person();这是定义了Person的一个实例person,实例可以调用Person.prototype这个对象的属性和方法,即age和getAge。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题