老老鼠

博客园 首页 新随笔 联系 订阅 管理

对象中包含什么:

JavaScript中的大多数对象可以分为如下两种类型:

Function对象,例如alert()函数,可以使用参数来改变这类对象的功能。

Object对象,这类对象不能像函数那样被调用,而且具有固定的功能-除非它们包含额外的Function对象 

为了提高效率,JavaScript也提供了下列内置对象:

1、Object是通用基础对象,可以使用它来创建简单的静态对象  

2、Function是被所有使用参数的对象复制的对象,也是在脚本中定义函数时所创建的对象  

3、Array是一种特殊的属性和方法的集合,比如使用其length属性可以通过循环迭代操纵这类对象也可以使用方括号  

4、String、Boolean和Number则分别用于表示字符串、布尔值以及数字所有内置对象都可以通过new关键字或者其它特殊语法来创建,花括号({})是Object的简写形式,而方括号(【】)则是Array的简写形式。 

 Window对象中的一切
  function myFunction(message){
    alert(message);
  }
  如果上面的函数是在JavaScript文件最顶层编写的没有被其它对象包含的代码,那么:
  myFunction('without window ojbect');
  window.myFunction('with window object');
  这两种调用方法结果是相同的,但是如果是在另一个对象中创建的这个函数,由于作用域链的关系,情况会变得复杂一些
 
function override(){
  //覆盖alert函数
  var alert = function(message){
    window.alert('overridden:' + message);
  }
  alert('alert');

  //在override()函数的作用域中调用原始的alert()函数
  window.alert('window.alert');
}

//在window的作用域中调用原始的alert()函数
alert('alert from outside');
 
在页面载入完成后,会有三个警告提示:"overridden:alert"、"window.alert"、"alert from outside",当然,如果在脚本文件最顶层如下写:
var alert = function(message){

  window.alert('overridden:' + message);
}
alert('test');
那么脚本会因为过渡递归而终止运行。因为这次是在脚本的最顶层覆盖的alert()方法,相当于你自己的方法替换了window.alert()方法。

创建你自己的对象
//创建构造函数
function myConstructor(message){
  alert(message);
  this.myMessage = message;
 
  //私有属性
  var separator = '-';
  var myOwner = this;

  //私有方法
  function alertMessage() {
    alert(myOwner.myMessage);
  }
  //在实例化时显示信息
  alertMessage();

  //特权方法(也是公有方法)
  this.appendToMessage = function(string){
    this.myMessage = separator + string;  //特权方法内可以访问私有成员separator
    alertMessage();
   }
}

//静态属性
myConstructor.name = 'Jeff';

//静态方法
myConstructor.alertName = function(){
  alert(this.name);
}


//添加一个公有方法
myConstructor.prototype.clearMessage = function(string){
  this.myMessage += ' ' + string;

  //这是错误的
  this.myMessage += separator + string;
}

在新实例上调用clearMessage将得到预期的效果
var myObject = new myConstructor('hello world');
myObject.clearMessage();
myObject.appendToMessage();    //特权方法也是公有方法

你可能已经注意到了,这个例子代码中也包含另外一个私有属性myOwner,它引用的是this。通过将this赋值给myOwner,你的私有方法就可以通过引用myOwner来访问myConstructor的实例。私有方法是存在于构造函数作用域中的自包含对象,它们实际上并不是prototype的方法,因此在私有方法内部this引用的只是私有方法的实例,而非myConstructor的实例。由于这些私有成员被严格限制在了构造函数的作用域中,因此也不能通过对象自己的公有方法来访问它们。要避免这一限制,可以使用特权方法 
对象字面量
var myObject = {
  propertyA: 'value',
  propertyB: 'value',
  methodA:function(){},
  methodB:function(){}
}
上面的代码跟下面的代码是等效的:
var myObject = new object();
myObject.propertyA = 'value';
myObject.proertyB = 'value';
myObject.methodA = function(){};
myObject.methodB = function(){};
也是就是,下面的简写形式是等效的:
var myObject = {}; var myObject = new object();

也可以使用对象字面量语法向prototype属性中添加所有仅有成员
myConstructor.prototype = {
  propertyA:'value',
  propertyB: 'value',
  methodA:function(){},
  methodB:function(){}  
}

通过Call()和apply()重新定义执行环境
function doubleCheck(){
  this.message = 'are you sure you want to leave?';
}
doubleCheck.prototype.sayGoodby = function() {
  return confirm(this.message);  
}
 
function initPage(){
  var clickedLink = new doubleCheck();
  var links = document.getElementsBytagName('a');
  for(var i = 0; i < links.length; i++){
    links.attachEvent("onclick",clickedLink.sayGoodby);
  }
}
window.attachEvent("onload",initPage);

这个例子中载入事件的预期效果是遍历页面中的所有链接,然后clickedLink.sayBoodby执行链接的click事件。但是由于this引用的对象会随着环境而改变,当例子中的sayGoodby()方法在<a>这个HTML元素的环境中执行时,this所引用的就是这个HTML元素,而不是你所期望的clickedLink对象,解决这个问题的方法就是使用Function对象的call()或apply()方法,用以改变函数的执行环境
clickedLink.sayGoodby.call(window)或者clickedLink.sayGoodby.apply(window);

如果sayGoodby带有参数可以使用下面方法:
clickedLink.sayGoodby.call(window,argument1,argument2,...);
clickedLink.sayGoodby.apply(window,arguments);
对于apply,应该将方法的参数做为数组放在第二个参数位置传递,这是它们的唯一区别

function bindFunction(obj,func){
  return function(){
    func.apply(obj,arguments);
  }
}
以上代码的关键在于,由bindFunction返回的匿名函数使用内部作用域中特殊的arguments参数,作为以外部作用域中的obj和func调用apply()时传递的额外参数,执行以上方法主要是为了给原始函数创建一个新环境。

posted on 2010-04-26 22:16  大老鼠  阅读(308)  评论(0编辑  收藏  举报