原文地址: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就指向谁,一定是直接调用而不是在调用链上出现过。
对象和属性的关系就好像一台机器中组件和零件的关系,可以装配别的零件的东西叫做组件,而装配到组件上的也可能还是组件,不过父组件上面并不会直接装配子组件上的零件。如果大家有机械方面的基础应该很容易理解这种模式,为了让大家可以更好地理解,学生再给您举个例子,比如我们将水杯放到背包里,那么背包就是个组件,然后又将背包放到车里,这时车就成了组件,背包就成了零件,不过要从车里直接拿水杯是拿不到的,只有从车里先拿到背包然后才能从背包里拿到水杯,当然,如果要想从背包里拿车上放着的光盘也是拿不到的,这需要从“车”这个组件中去拿。
嵌套对象的作用主要是便于维护,就好像将杂七八糟的东西都分类放到各种各样的小盒子里面,然后再将小盒子分类放到大盒子里,最后将所有大盒子都放到箱子里,这样维护和使用起来就都方便了。在有的资料里会将这种嵌套对象叫做“命名空间”或者“包”,无论叫什么我们只要理解了其本质就可以了,当然在遇到那种叫法的时候我们也要明白别人所指的是什么。