(转)JS中的对象

1.对象

要有对象, 就先要有创建对象的方法. 
在C++/Java等语言, 这个方法就是实例化XXX类的一个实例xxx.
而在JavaScript的世界里实际没有类的东西, 当然仍然可以用"类"和"实例"等惯用语来描述JavaScript中类似的行为, 但其机制是完全不同的. JavaScript的对象是由构造函数创建的, 每个对象都有constructor属性表示创建该对象的构造函数:

function Test() { this.a = "hello"; }
var test = new Test(); // 由Test构造函数创建
alert(test.constructor);

var o = { a: "hello" };
//实际相当于
var o_ = new Object();
o_.a = "hello"; // 由Object构造函数创建
alert(o.constructor);

构造函数也是对象, 那构造函数是由什么创建? 内建的Function函数:

function Test(a, b)
{
    alert(a+b);
}
// 相当于:
Test = new Function(["a", "b"], "alert(a+b);");

Function函数又是由什么创建? 实际上Function是本机代码实现的固有对象. 不过为了一致性, Function也有constructor属性, 该属性指向它自己. 接上面的代码:

/* 输出 function Function(){
            [native code]
        }
*/
alert(Test.constructor);

alert(Test.constructor.constructor === Test.constructor); // true
alert(Test.constructor === Object.constructor); // true

2原型

prototype是构造函数的一个属性, 该属性指向一个对象. 而这个对象将作为该构造函数所创建的所有实例的基引用(base reference), 可以把对象的基引用想像成一个自动创建的隐藏属性. 当访问对象的一个属性时, 首先查找对象本身, 找到则返回; 若不, 则查找基引用指向的对象的属性(如果还找不到实际上还会沿着原型链向上查找,  直至到根). 只要没有被覆盖的话, 对象原型的属性就能在所有的实例中找到.
原型默认为Object的新实例, 由于仍是对象, 故可以给该对象添加新的属性:

// prototype默认为new Object(); 为了方便, 记为p_obj
function Person(name) {
    this.name = name;
}

// 为 p_obj 增加 sayName 属性
Person.prototype.sayName = function(){
    alert(this.name);
}

var john = new Person("John"); // john 的 base reference指向p_obj
var eric = new Person("Eric");  // eric 的 base reference也是指向p_obj

// 注意sayName代码中的this将指向实例化后的对象(this绑定)
john.sayName(); // john对象本身没有sayName属性, 于是访问原型对象p_obj的sayName属性
eric.sayName(); // 访问同一个原型对象p_obj的sayName属性

var tmp = Person.prototype;
tmp.boss = "David";
// 于这个运行点, p_obj已经被修改
// 根据上述属性访问流程, 新的修改(boss属性)能反映到所有的实例, 包括已经创建和即将创建的
alert("John‘s boss is " + john.boss);
alert("Eric‘s boss is " + eric.boss);

// hisCar和sayCar属性将增加到john对象而不是p_obj对象..
john.hisCar = "Audi";
john.sayCar = function(){
    alert(this.name + " has a car of " + this.hisCar);
}
john.sayCar();
// ..因此下一句将错误, 因为eric对象本身和原型p_obj都没有sayName属性
/* eric.sayCar(); */

2.2 原型链
除了能修改prototype指向的对象, 还能修改prototype指向哪一个对象, 即为prototype赋予一个不同的对象. 这可以实现一种简单的继承:

function Superman() {}
Superman.prototype.sayHello = function(){
    alert("I‘m a superman.");
}

function SupermanCan(skill){
    this.skill = skill;
}
// 为prototype赋予Superman的实例..
SupermanCan.prototype = new Superman();
// ..再动态添加新的属性
SupermanCan.prototype.sayMore = function(){
    this.sayHello(); // 调用"父类"的方法
    alert("I can " + this.skill);
}

var david = new SupermanCan("fly");
// output: I‘m a superman. I can fly
david.sayMore();

如果先实例化出一个对象, 再为构造函数prototype赋予一个不同的对象, 将会: 已经创建的对象的基引用不变, 将来创建的对象的基引用为新的原型对象:

var f1 = {echo: function() { alert("sound"); } };
function Foo() {};
var foo = new Foo(); // foo的基引用指向Object实例
Foo.prototype = f1;
/* 未定义, 因为这是"foo对象自己或者基引用指向的对象有echo属性吗?"
   而不是"foo对象自己或者Foo.prototype指向的对象有echo属性吗?" */
alert(foo.echo);

var foo2 = new Foo(); // foo2的基引用指f1对象
foo2.echo(); // output: sound

所有的构造函数的prototype都不能为空, 就是说Superman.prototype = null 会被解释引擎无视;  另一方面, Object构造函数也有prototype属性(该属性是只读的, 可以为原型增加属性,但不能赋予不同的对象), 故因此可以有多层的原型链, 但原型链的根必定会是Object.prototype . 这意味着给Object.prototype增加属性影响到所有对象:

Object.prototype.echo = function() {
    alert("hello");
}

// echo属性将增加到所有对象固有对象和自定义对象

var arr = new Array();
arr.echo();
Array.echo();

function ObjCons()    {
    this.dummy = "d";
}
var obj = new ObjCons();
obj.echo();
ObjCons.echo();

3. 构造函数和new的实质
构造函数是一个地地道道的函数, 一个函数之所以能成为构造函数, 是因为new运算符:

this.msg = "window";

function Test()
{
    alert(this.msg);
}

Test(); // window
var test = new Test(); // undefined. 因为test对象没有定义msg属性

二者区别在于如何切入对象: Test() 在某个对象(例子中为window)的上下文上执行代码, 即this指向这个对象; new Test()创建一个新对象, 并以这个新的对象为上下文(this指向新对象)执行代码, 然后返回这个新对象. 
假如有个函数:

function Test() {
    var dummy = "have money";
    this.wish = dummy;
    doSomeThing();

}

结合以上的所有论述, 可以推测new Test()行为的伪代码表示为:
      创建一个新对象temp;
      temp.constructor = Test;
      temp.(base reference) = Test.prototype; // 这一句先于代码体执行, 意味着构造函数里的this.xxx能访问原型对象的属性xxx
      bind: this = temp; // 将this绑定到temp对象
      // 开始执行函数代码
      var dummy = "have money";
      this.wish = dummy; // 为temp对象添加wish属性
      doSomeThing();
      ....
      // 结束执行函数代码
      return temp;

时间: 2024-08-25 19:30:46

(转)JS中的对象的相关文章

swfupload js中 file 对象的属性

name=3cc68cfc60b87e6dd6887d8a.jpg modificationdate=Wed   Apr 21 15:48:30 UTC+0800 2010 filestatus=-1 post=[object   Object] type=.jpg index=0 size=29006 creationdate=Wed Apr 21 15:48:38 UTC+0800   2010 id=SWFUpload_0_0swfupload js中 file 对象的属性,布布扣,bub

js实现小时钟,js中Date对象的使用?

介绍一下js中Date对象的使用 dateObj = new Date() dateObj = new Date(dateValue) dateObj = new Date(year,month,date[,hours[,minutes[,seconds[,ms]]]]); 以下有一个小样例 <script type="text/javascript"> function setTime(){ //获得如今的时间 var now = new Date(); var year

js中推断对象详细类型

大家可能知道js中推断对象类型能够用typeof来推断. 看以下的情况 <script> alert(typeof 1);//number alert(typeof "2");//string alert(typeof [1,2,3]);//object alert(typeof {"name":"zhuhui"})//object </script> 从上面中我们能够看出数组和普通对象用typeof推断出来都是objec

js中window对象详解以及页面跳转

js中window对象详解以及页面跳转 转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%90%9C/39219.shtml 1.window.top.window.location = "index.asp"; 2.window.top.location.href="index.asp" 3. window.top.location.replace("index.asp");

JS中有关对象的继承以及实例化、浅拷贝深拷贝的奥秘

一.属性的归属问题 JS对象中定义的属性和方法如果不是挂在原型链上的方法和属性(直接通过如类似x的方式进行定义)都只是在该对象上,对原型链上的没有影响.对于所有实例共用的方法可直接定义在原型链上这样实例化的的时候就不用对每个实例定义该属性方法,所有的实例均具有该方的引用见最后的输出. function Myclass(){ this.x=" x in Myclass"; this.get=function(){}//每次实例化对象,每个对象的该方法都是独立的,是不相同的 } Mycla

JavaScript学习12 JS中定义对象的几种方式【转】

avaScript学习12 JS中定义对象的几种方式 转自:  http://www.cnblogs.com/mengdd/p/3697255.html JavaScript中没有类的概念,只有对象. 在JavaScript中定义对象可以采用以下几种方式: 1.基于已有对象扩充其属性和方法 2.工厂方式 3.构造函数方式 4.原型("prototype")方式 5.动态原型方式 一.基于已有对象扩充其属性和方法 <script type="text/javascript

JS中的对象和方法简单剖析

众所周知,在js中对象就是精髓,不理解对象就是不理解js. 那么什么事js中的对象呢? 在js中,几乎一切皆对象: Boolean ,String,Number可以是对象(或者说原生数据被认作对象): Dates ,Maths,Regexps,Arrays,Funcitons,当然Objects,这些都是对象: JS中,所有值,除了原生值,都是对象:这些原生值包括:strings,numbers('3.14'),true,false,null和undefined 对象是包含变量的变量,js变量可

JavaScript学习12 JS中定义对象的几种方式

JavaScript学习12 JS中定义对象的几种方式 JavaScript中没有类的概念,只有对象. 在JavaScript中定义对象可以采用以下几种方式: 1.基于已有对象扩充其属性和方法 2.工厂方式 3.构造函数方式 4.原型("prototype")方式 5.动态原型方式 一.基于已有对象扩充其属性和方法 <script type="text/javascript"> var object = new Object(); object.name

浅解析js中的对象

浅解析js中的对象 说到对象,我首先想到的是每逢过年过节,长辈们老是开玩笑的问我“你找了对象没?”.不说大家都知道,这里的“对象”指的是“女朋友”,但是今天我想要说的js中的“对象”和我们生活中谈到的“对象”不是同一回事,但是其中也有着很多相似之处.    在讲js中的对象之前,我想先抛出几个疑问:    什么是对象?    对象有哪些?    对象能做什么?    如何创建对象?    如何对对象进行操作?    对象有特性么?有的话有哪些特性?    对象有属性么?有的话有哪些?对属性如何操

js中判断对象具体类型

大家可能知道js中判断对象类型可以用typeof来判断.看下面的情况 <script> alert(typeof 1);//number alert(typeof "2");//string alert(typeof [1,2,3]);//object alert(typeof {"name":"zhuhui"})//object </script> 从上面中我们可以看出数组和普通对象用typeof判断出来都是object