Javascript 面向对象化写法——语法篇

本编参考:http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html 系列,总结如下

一.几个重要关键字

1.this —— 指当前的对象,若在全局范围,则指当前页面对象window,如果是函数中使用this,则指的是调用这个函数的对象。firebug一下demo:

function sayHi() {
  
  console.debug(this);
}


var obj = {
  sayHi: sayHi,
  sayHi2: function() {
    return function() {
      console.debug(this);
    }
    
  }
};


sayHi(); // 结果为window对象

obj.sayHi(); // 结果为obj对象

obj.sayHi2()(); //  结果为window对象

 解析:在javascript当中,一切皆为对象,function也是,所以可以看到全局函数sayHi可以像变量一般pass给obj的sayHi属性。三个函数调用的,前两个不用多解析,看第三个,其实等价于下面写法:

var f = obj.sayHi2();
f();

 sayHi2函数返回一个函数对象,赋予变量f,f就是个函数了,然后 f 被window调用执行,如此就这么回事了。

再看一个demo:

function TestThis () {
 
 this.oham = 'oham';
  console.debug(this);
 
}

TestThis();   // window对象
new TestThis();  // TestThis 对象实例本身

 对于TestThis();的结果不奇特,而new TestThis();之神奇在于new,其内部机制在下就不懂了...只可以看出,通过new XXX();这样调用,XXX方法中的this就指向XXX构造出的对象实例本身了。

2.apply与call

接着上面的例子,介绍apply 与 call,它们均是全局函数,归Function所有(Function属于javascript内部对象,不是Function的对象是没有这两个方法的)。 接上文的demo:

...
obj.sayHi2()();  //结果为window对象

obj.sayHi2().apply(obj);   // 结果为obj对象
obj.sayHi2().call(obj);   // 结果为obj对象

 apply 与 call 的 作用是改变函数中this的指向,即使函数看起来好像被谁调用一样,其作用域也是那个谁的。 

apply 与 call 的区别,仅仅是参数定义不同,请看如下demo:

function ml(me, mm) {
  
  console.log(this);
  
  if( this === window ) {
    console.log(me + ',' + mm + ' not possible in public');
  }else {
    console.log(me + ',' + mm + ' so happy');
  }
  
}

var hotel = {};


ml('me', 'mm');  

ml.apply(hotel, ['me', 'mm']);

ml.call(hotel, 'me', 'mm');

 请实践一下,代码,便知知道,apply的定义的参数列表是个数组,call是参数列(估计是function call(obj, params...))。

**至此深觉有必要介绍javascript中闭包的概念。闭包,指的是语法上表示包含不被计算的变量的函数,也就是说,函数可以使用函数之外定义的变量。

demo(以下摘自w3cschool):

var sMessage = "hello world";

function sayHelloWorld() {
  alert(sMessage);
}

sayHelloWorld();

 在上面这段代码中,脚本被载入内存后,并没有为函数 sayHelloWorld() 计算变量 sMessage 的值。该函数捕获 sMessage 的值只是为了以后的使用,也就是说,解释程序知道在调用该函数时要检查 sMessage 的值。sMessage 将在函数调用 sayHelloWorld() 时(最后一行)被赋值,显示消息 "hello world"。

再看看自己的一个demo:

var outSide = 'madom';

var room = {
  mm : 'mm',
  watch: function(me) {
    
    return function () {
      
      if(this.outSide) {  //尝试
        console.debug(me + ' can watch ' + this.outSide);
      }else {
        console.debug(me + ' can\'t watch  outSide, but never mind.');
      }
       
      if(this.mm) {   //尝试
          console.debug(me + ' can watch ' + this.mm);
      }else {
          console.debug(me + ' can\'t watch mm, not happy');
      }
    } 
  },
  
  touch: function (me) {
  
      if(this.outSide) { //尝试
        console.debug(me + ' can touch ' + this.outSide + ', but won\'t do that');
      }else {
        console.debug(me + ' can\'t touch outSide, but never mind.');
      }
       
      if(this.mm) { //尝试
          console.debug(me + ' can touch ' + this.mm + ', so cool...');
      }else {
          console.debug(me + ' can\'t touch mm, not happy');
      }
  }
};

var watchFunc = room.watch('I');

//全局调用
watchFunc();   
console.log('-------------------------------------');
//room范围调用
watchFunc.apply(room);

console.log('============================================');

//room范围调用
room.touch('I');
console.log('----------------------------------------');
//全局调用
room.touch.apply(this, ['I']);

 结果为:

"I can watch madom"
"I can't watch mm, not happy"
"-------------------------------------"
"I can't watch  outSide, but never mind."
"I can watch mm"
"============================================"
"I can't touch outSide, but never mind."
"I can touch mm, so cool..."
"----------------------------------------"
"I can touch madom, but won't do that"
"I can't touch mm, not happy"

 这个结果好解析,this为谁调用就是谁,接着请尝试把demo中标有//尝试的if 语句中的"this."删除,

情况会如下:

"I can watch madom"
"Uncaught ReferenceError: mm is not defined (line 15)"

 执行到watch函数的if(mm) 这句出错了,无论apply部apply结果都一样,原因具体我就不清楚了,这里只是证实了,对于一个变量如name, name 并不是等价于this.name(跟java大不同) ,JS的解释程序不会为你做这个,当函数被调用的时候,它只会先从当前函数范围去找,若无命中变量,则直接到全局范围去找。可以把mm部分的代码去掉,只留outSide的,结果是无论apply与否,结果都能访问的变量outSide。

 3.prototype——对该对象的对象原型的引用。对于所有的对象,它默认返回 Object 对象的一个实例(w3c定义)。

prototype本质上还是一个JavaScript对象,个人觉得上述定义不太妥当,实际上prototype感觉更像对象的一个模板,而非实例, 并且每个函数都有一个默认的prototype属性。 以demo为证:

var room = {
  mm: 'mm',
  watch: function () {
  }
};

console.log(room.prototype);    // undefined
console.log(room.valueOf());    //  room object

相关推荐