function Person(name){
this.name=name;
}
Person.prototype.getName=function(){
return this.name;
}
//调用函数
var person=new Person("Nicholas");
alert(person.getName());
疑问:
同一个函数,为啥在去掉this(原型模式中的this)后代码如下:
Person.prototype.getName=function(){
return name;
}
出现如下的错误:
Test3.html:102 Uncaught ReferenceError: age is not defined
this不去掉的话,就会输出Nicholas;
Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
原型和构造函数中的this都指向new出来的对象,构造函数中的代码是为name赋值,而原型中的代码是访问name的值,去掉this就是在全局环境中找name了,找不到所以返回undefined。
不要把原型链和变量作用域搞混了,前者是为了实现对象的继承,后者方便的解释了变量的查找规则。
name的意思是查找变量namethis.name的意思是查找对象this的name属性这两者的意思是不一样的,前者按照变量作用域的规则进行查找,后者仅仅是访问某个对象的一个属性。
1、 变量作用域(ES5.1之前,先理解简单的,也先忽略某些闭包)
在JS里面只有一种作用域,那就函数作用域。
变量的查找就是看你代码中的
{}(专指函数定义中的{}),每次函数定义会形成一级作用域。在某个作用域内使用var定义的变量就是定义在该作用域中的变量。当写下一个变量,首先在本作用域中查找是否有该变量,否则递归的向上一级作用域中查找。比如
return a+b中的a会在本作用域中查找到一个定义在本作用域中的变量,故a为0,但是b却本作用域中查找不到,所以去上一级去查找,即fn形成的作用域,故b为2。在console.log(a)依旧是这样,所以a为1。查找不到的就会抛出异常。由于此种规则,所以不论是
obj.a()还是fn()输出都是0,同样obj.b()返回2。2、对象属性的查找规则
当写下
obj.name(获取其值)的时候,就是按照对象的属性查找规则查找。当执行
var p = new Person("n");的时候,其实解释器暗暗的做了一件事情p.__proto__ = Person.prototype。当访问p.getName,解释器首先查找在p中有没有属性getName,否则递归的去__proto__中查找这个属性。所以会找到Person.prototype中定义的那个函数(如果最终找不到则返回undefine,这个跟变量查找不到是不同的)。同样p.say()返回的会是"hello!"。3、
this的值在JS
this其实是一个关键字,不是变量。因为不是变量所以其查找规则是另外的一套。下面只说一下与本问题有关的(记住就好没有为什么)。其余的参考这里(1)
var p = new Person("n")的时候,其实类似与如下代码(仅仅作为说明)。即
this是一个新创建的对象,并且最终会付给p,所以对象p是含有属性name的。(2)
p.getName()的时候。在执行函数getName的时候,其里面的this是p。所以此时的
this.name其实就是p.name4、 结论
所以
return name + this.name,中name按照变量的查找规则,结果是“His name is ”而this.name就是p.name是"n"。至于为什么只是抛出
age未定义,是因为在浏览器里面在全局定义了一个变量name其值为空字符串。如果只是测试的话建议换一个变量名。