在 JavaScript 中,每当定义一个对象(或函数)时候,对象中都会包含一些预定义的属性,其中一个属性就是原型对象 prototype

var myObject = function( name ) {
this.name = name;
return this;
}; console.log(typeof myObject.prototype); // object myObject.prototype.getName = function() {
return this.name;
};

上面的代码创建了一个函数,然后赋值给 myObject。如果我名调用 myObject(),它将返回window 对象。因为它是在全局作用域内定义的,而且它还没有被实例化,所以 this 直接指向全局对象:

console.log(myObject() === window); // true

原型链

JavaScript 中定义或实例化任何一个对象的时候,它都会被附加一个名为 __proto__ 的隐藏属性,原型链正是依靠这个属性才得以形成。但是千万别直接访问 __proto__ 属性,因为有些浏览器并不支持直接访问它。另外 __proto__ 和 对象的 prototype 属性也不是一回事,它们各自有各自的用途。

怎么理解呢?其实,当我们创建 myObject 函数时,实际上是创建了一个 Function 类型的对象:

console.log(typeof myObject); // function

这里要说明一下,Function 是 JavaScript 中预定义的一个对象,所以它也有自己预定义的属性(如length 和 arguments)和方法(如 call 和 apply),当然也有 __proto__,以此实现原型链。也就是说,JavaScript 引擎内可能有类似如下的代码片段:

Function.prototype = {
arguments: null,
length: 0,
call: function() {
// secret code
},
apply: function(){
// secret code
},
...
};

事实上,JavaScript 引擎代码不可能这样简单,这里只是描述一下原型链是如何工作的。

我们定义了一个函数 myObject,它还有一个参数 name,但是并没有给它任何其它属性,例如length 或者其它方法,如 call。那么下面这段代码为啥能正常执行呢?

console.log(myObject.length); // 结果:1,是参数的个数

这是因为我们定义 myObject 时,同时也给它定义了一个 __proto__ 属性,并赋值为Function.prototype(参考前面的代码片段),所以我们能够像访问其它属性一样访问myObject.length,即使我们并没有定义这个属性,因为它会顺着 __proto__ 原型链往上去找length,最终在 Function 里面找到了。

那为什么找到的 length 属性的值是 1,而不是 0 呢,是什么时候给它赋值的呢?由于 myObject是 Function 的一个实例:

console.log(myObject instanceof Function); // true
console.log(myObject === Function); // false

当实例化一个对象的时候,对象的 __proto__ 属性会被赋值为其构造者的原型对象,在本示例中就是 Function,此时构造器回去计算参数的个数,改变 length 的值。

console.log(myObject.__proto__ === Function.prototype); // true

而当我们用 new 关键字创建一个新的实例时,新对象的 __proto__ 将会被赋值为myObject.prototype,因为现在的构造函数为 myObject,而非 Function

var myInstance = new myObject('foo');
console.log(myInstance.__proto__ === myObject.prototype); // true

新对象除了能访问 Function.prototype 中继承下来的 call 和 apply 外,还能访问从 myObject 中继承下来的 getName 方法:

console.log(myInstance.getName()); // foo

var mySecondInstance = new myObject('bar');

console.log(mySecondInstance.getName()); // bar
console.log(myInstance.getName()); // foo

其实这相当于把原型对象当做一个蓝本,然后可以根据这个蓝本创建 N 个新的对象。

prototype 的典型示例

用过 jQuery 或者 Prototype 库的朋友可能知道,这些库中通常都会有 trim 这个方法。

示例:

String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, '');
};

trim 用法:

' foo bar   '.trim(); // 'foo bar'

但是这样做又有一个缺点,因为比较新版本的浏览器中的 JavaScript 引擎在 String 对象中本身就提供了 trim 方法, 那么我们自己定义的 trim 就会覆写它自带的 trim。其实,我们在定义 trim 方法之前,可以做个简单的检测,看是否需要自己添加这个方法:

if(!String.prototype.trim) {
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, '');
};
}

检查一下,如不存在 trim 这个方法,定义一个。

via http://net.tutsplus.com/tutorials/javascript-ajax/prototypes-in-javascript-what-you-need-to-know/

JavaScript 的原型对象 Prototype的更多相关文章

  1. JavaScript的原型对象prototype、原型属性__proto__、原型链和constructor

    先画上一个关系图: 1. 什么是prototype.__proto__.constructor? var arr = new Array; 1. __proto__是原型属性,对象特有的属性,是对象指 ...

  2. [js高手之路]使用原型对象(prototype)需要注意的地方

    我们先来一个简单的构造函数+原型对象的小程序 function CreateObj( uName, uAge ) { this.userName = uName; this.userAge = uAg ...

  3. js高级——构造函数,实例对象和原型对象——prototype、__proto__和constructor构造器

    一.前言 了解JavaScript面向对象,需要先了解三个名词: 构造函数,实例对象和原型对象. 注意:JavaScript中没有类(class)的概念,取而代之的是构造函数,两者类似却又有很大的差别 ...

  4. JavaScript中原型对象的应用!

    JavaScript中原型对象的应用! 扩展内置对象的方法 我以数组对象为例! // 原型对象的应用 扩展内置对象方法! Array.prototype.sum = function() { var ...

  5. JavaScript 之 原型对象、对象原型 —— { }

    JavaScript -- 构造函数 // 构造函数 function Player(name, age) { this.name = name; this.age = age; } JavaScri ...

  6. 原型对象prototype和原型属性[[Prototype]]

    构造器:可以被 new 运算符调用, Boolean,Number,String,Date,RegExp,Error,Function,Array,Object 都是构造器,他们有各自的实现方式. 比 ...

  7. 构造函数、原型对象prototype、实例、隐式原型__proto__的理解

    (欢迎一起探讨,如果有什么地方写的不准确或是不正确也欢迎大家指出来~) PS: 内容中的__proto__可能会被markdown语法导致显示为proto. 建议将构造函数中的方法都定义到构造函数的原 ...

  8. 【原型模式】--重写原型对象prototype的影响

    //[原型模式]--重写原型对象prototype的影响 2014-12-12//定义构造函数function Person() { }//直接指定构造函数的原型为一个对象(为了简化逐个给原型添加成员 ...

  9. javascript原型对象prototype

    “我们创建的每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法.” 引用类型才具有prototype属性 ...

随机推荐

  1. POJ3687——Labeling Balls(反向建图+拓扑排序)

    Labeling Balls DescriptionWindy has N balls of distinct weights from 1 unit to N units. Now he tries ...

  2. 蓝牙(3)如何通过蓝牙传输数据及UUID详介

    如何通过蓝牙传输数据 通过蓝牙传输数据与Socket类似.在网络中使用Socket和ServerSocket控制客户端和服务端的数据读写.而蓝牙通讯也由客户端和服务端Socket来完成.蓝牙客户端So ...

  3. [ffmpeg 扩展第三方库编译系列] 关于 mingw32 下编译libcaca

    在编译前最好先看一下帮助 ./configure --help 开始编译 ./configure  --disable-shared --disable-cxx \ --disable-csharp ...

  4. poj 2676 Sudoku ( dfs )

    dfs 用的还是不行啊,做题还是得看别人的博客!!! 题目:http://poj.org/problem?id=2676 题意:把一个9行9列的网格,再细分为9个3*3的子网格,要求每行.每列.每个子 ...

  5. POJ 2135 Farm Tour(最小费用最大流,变形)

    题意:给一个无向图,FJ要从1号点出发到达n号点,再返回到1号点,但是路一旦走过了就会销毁(即回去不能经过),每条路长度不同,那么完成这趟旅行要走多长的路?(注:会有重边,点号无序,无向图!) 思路: ...

  6. 【MooTools】

    MooTools a compact javascript frameworkhttp://mootools.net/docs/core 30天学会 MooTools 教学(1): 认识MooTool ...

  7. ssh-keygen+ssh-copy-id 在linux下实现ssh无密码登录访问

    环境: 192.168.2.10 192.168.2.11 实现:2.10 ssh无需密码登录到2.11 在2.10 ssh到2.11机器上,需要密码,这样对一些脚本工作不方便,因为需要密码,也就是需 ...

  8. http://www.cnblogs.com/youfan/articles/3216816.html

    我对 CodeFirst 的理解,与之对应的有 ModelFirst与 DatabaseFirst ,三者各有千秋,依项目实际情况自行选择. 1.开发过程中先行设计数据库并依此在项目中生成 *.dbm ...

  9. jQuery.autoComplete 多参数

    query 版本 1.3.2插件默认的 参数 是q 如果需要传递多个参数呢?$("#stylistname").autocomplete("/page/autostyli ...

  10. 将java应用程序打包成可执行文件

    准备工作:我用的打包软件是installanywhere.因此要先下载这个软件,这里提供一个下载地址http://www.52z.com/soft/21747.html.(网页上写的有破解方法) 详细 ...