首页
点运算符与this
点运算符与this
版权声明:本文为原创内容,转载请声明出处。
原文地址:http://www.excelib.com/article/282/show

点运算符

点运算符用来操作对象的属性,这种的操作可以分为获取值和赋值两种类型,在赋值的情况下如果对象原来没有所操作的属性则会添加,如果有则会修改其值,比如下面的例子

1
2
3
4
var person = {name:"maker"};
person.age = 15;                          //添加age属性
console.log(person.name);                 //获取name属性
person.name = "peter";                    //修改name属性


this的含义

很多开发者都对JavaScript中的this理解的不是很清楚,很多时候会因为不正确地使用this而造成不必要的错误,学生下面就来给大家介绍JavaScript中的this。

要正确理解this首先要将我们前面学习过的三种子类型区分清楚,这三种子类型是不可以相互调用的,只有区分清楚这三种子类型之后才可能正确理解this的含义。

区分清楚三种子类型之后再理解this就非常简单了,只需要记住一句话就可以了,那就是“谁直接调用方法this就指向谁”。也就是说方法的点前面的对象就是this,只要记住这一原则就不会对this的使用产生错误了,我们来看下面的例子

1
2
3
4
5
6
7
8
9
10
11
var color = "red";
 function Obj(){
     var color = "black";
 }
 Obj.color = "green";
 Obj.prototype.logColor = function(){
     console.log(this.color);
 }
 var o = new Obj();
 o.color = "blue";
 o.logColor();


 这个例子中一共有四个color,一个是全局变量、一个是Obj的局部变量、一个是Obj的属性还有一个是Obj创建出来的实例对象o的属性,logColor方法是Obj的prototype中的方法属性,他里面打印了this.color的值,大家思考一下这里会打印出什么内容呢?

最后的结果会打印出"blue",这是因为logColor方法是被o对象直接调用的,所以最后就会打印出o中的blue。

关联方法后的this

我们先来看下面的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function logColor(){
     console.log(this.color);
 }
  
 function Obj(){}
 var o = new Obj();
  
 Obj.color = "red";
 o.color = "blue";
  
 Obj.logColor = logColor;
 o.logColor = logColor; 
  
 Obj.logColor();                                 //red
 o.logColor();                                   //blue

这个例子中首先定义了一个独立的函数logColor,然后定义了Obj方法对象并使用Obj创建了实例对象o,接着给Obj和o分别添加了color属性和logColor方法属性,logColor属性都是直接关联到了独立的函数logColor,这时调用Obj的logColor就会打印出Obj的color值red,调用实例o的logColor则会打印出o的color值blue,也就是说谁调用方法this就代表谁。

内部函数中的this

我们先来看下面的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
var v = 1;
 function Program(){
     var v = 2;
     this.v = 3;
 }
 Program.prototype.logV = function () {
     function innerLog(){
         console.log(this.v);
     }
     innerLog();
 }
 var pro = new Program();
 pro.logV();

大家觉得这里会打印出了什么内容呢?可能有的读者觉得很简单,既然是pro对象调用的当然会打印出pro对象中v的值——3,但是实际上1才是正确答案。我们要注意,在这个例子中实际打印的操作并不是在logV方法中执行的,而是在logV中调用他的内部方法innerLog来完成的,所以这里的this应该看innerLog方法前的对象,而不是logV方法前面的对象,而innerLog方法是直接调用的,前面并没有对象,这种情况下的this就会指向全局对象window,而window的v属性就是全局变量v,所以结果会打印出1。

这时如果我们想在内部函数中打印出调用外部函数的对象的属性(比如在innerLog方法中打印出pro对象中的v属性)可以有三种方法来实现:1、在外部方法中将this保存到一个变量然后在内部函数中调用;2、在外部方法中将内部方法关联到对象上并使用对象调用内部方法;3、将内部方法改为接收参数的方法,并在外部方法中将属性通过变量传入内部方法。比如上面的logV方法可以这么处理

方法1

1
2
3
4
5
6
7
Program.prototype.logV = function () {
     var instance = this;
     function innerLog(){
         console.log(instance.v);
     }
     innerLog();
 }


方法2

1
2
3
4
5
6
7
Program.prototype.logV = function () {
     function innerLog(){
         console.log(this.v);
     }
     this.innerLog = innerLog;
     this.innerLog();
 }


方法3

1
2
3
4
5
6
Program.prototype.logV = function () {
     function innerLog(v){
         console.log(v);
     }
     innerLog(this.v);
 }


这三种方法都会打印出pro对象的属性v(3)。所以大家要明白,内部函数中的this跟我们的原则“谁直接调用方法this就是谁”并不冲突,只是要注意实际处理业务的函数到底是谁调用的就可以了。

对象的属性不可继承

属性不可继承指的是如果对象有多个层次的话,父子对象里的属性不可以相互继承和调用,我们来看下面的例子

1
2
3
4
5
6
7
8
9
10
11
12
function logV(){
     console.log(this.v);
 }
  
 var obj = {v:1};
 obj.sonObj = {};
  
 obj.logV = logV;
 obj.sonObj.logV = logV; 
  
 obj.logV();                                        //1
 obj.sonObj.logV();                            // undefined

这个例子中定义了一个obj对象以及obj的子对象sonObj,obj中有一个属性v,sonObj中没有自己的属性,然后将logV方法分别关联到两个对象,接着分别调用他们的logV方法,最后obj可以打印出v,obj.sonObj找不到v,会打印出undefined,这就说明obj.sonObj不可以调用obj中的属性。所以在使用我们的原则时一定要记住是谁直接调用了方法this就指向谁,一定是直接调用而不是在调用链上出现过。

对象和属性的关系就好像一台机器中组件和零件的关系,可以装配别的零件的东西叫做组件,而装配到组件上的也可能还是组件,不过父组件上面并不会直接装配子组件上的零件。如果大家有机械方面的基础应该很容易理解这种模式,为了让大家可以更好地理解,学生再给您举个例子,比如我们将水杯放到背包里,那么背包就是个组件,然后又将背包放到车里,这时车就成了组件,背包就成了零件,不过要从车里直接拿水杯是拿不到的,只有从车里先拿到背包然后才能从背包里拿到水杯,当然,如果要想从背包里拿车上放着的光盘也是拿不到的,这需要从“车”这个组件中去拿。

嵌套对象的作用主要是便于维护,就好像将杂七八糟的东西都分类放到各种各样的小盒子里面,然后再将小盒子分类放到大盒子里,最后将所有大盒子都放到箱子里,这样维护和使用起来就都方便了。在有的资料里会将这种嵌套对象叫做“命名空间”或者“包”,无论叫什么我们只要理解了其本质就可以了,当然在遇到那种叫法的时候我们也要明白别人所指的是什么。