`
robinqu
  • 浏览: 90399 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

JavaScript Prototype基础

阅读更多
The prototype Property
引用
prototype property that refers to a predefined prototype object


Prototype属性是指一个早已确定的原型对象

Classes, Constructors, and Prototypes
引用
JavaScript does not support true classes the way that languages like Java, C++, and C# do.


JavaScript不支持真正的类继承,事实上是它是一个基于原型继承的,这和传统语言很不一样。

在JavaScript the Good Parts一书中,Douglas Crockford这样描述:
引用
It is Lisp in C's Clothing


在JS中,新建一个对象可以用对象的直接量{},或者通过构造函数

var array = new Array(10);
var today = new Date( );


定义我们自己的对象
// Define the constructor.
// Note how it initializes the object referred to by "this".
function Rectangle(w, h) {
    this.width = w;
    this.height = h;
    // Note: no return statement here
}

// Invoke the constructor to create two Rectangle objects.
// We pass the width and height to the constructor
// so that it can initialize each new object appropriately.
var rect1 = new Rectangle(2, 4);    // rect1 = { width:2, height:4 };
var rect2 = new Rectangle(8.5, 11); // rect2 = { width:8.5, height:11 };


在构造函数中始终要用this来引用当前对象,以来添加对象的属性

如果要添加方法:
// Create a Rectangle object
var r = new Rectangle(8.5, 11);
// Add a method to it
r.area = function( ) { return this.width * this.height; }
// Now invoke the method to compute the area
var a = r.area( );


当创建了对象之后再添加方法显得有些麻烦,我们可以这样:
function Rectangle(w, h) {
    this.width = w;
    this.height = h;
    this.area = function( ) { return this.width * this.height; }
}


引用
It is inefficient to use regular properties for methods that are intended to be shared by all objects of the same class (that is, all objects created with the same constructor).

这样问题就来了。以这种常规属性来存储对象方法是很没有效率的,这种方法本该是没个这样的对象实例所“共享”的,而不要每次新建一个对象都要新建一个这个方法的拷贝。

这时我们的原型对象就上场了

引用
a JavaScript object inherits properties from its prototype.

After creating the empty object, new sets the prototype of that object.
The prototype of an object is the value of the prototype property of its constructor function.

All functions have a prototype property that is automatically created and initialized when the function is defined.
The initial value of the prototype property is an object with a single property. This property is named constructor and refers back to the constructor function with which the prototype is associated.

JS的对象都会从它的原型那里继承属性。
我们在new一个对象的时候,new关键字就会设定对象的prototype属性,其值就是该对象的prototype对象的引用

函数也是对象,所以它也不例外有一个在定义时就有的prototype属性

Prototype属性初始时所指向的Prototype对象只有一个constructor属性,这个属性又指向了与这个prototype对象相关的构造函数

// The constructor function initializes those properties that
// will be different for each instance.
function Rectangle(w, h) {
    this.width = w;
    this.height = h;
}

// The prototype object holds methods and other properties that
// should be shared by each instance.
Rectangle.prototype.area = function( ) { return this.width * this.height; }


上面这个例子中,在构造函数里定义了每个实例都会有不同值的属性,而在其Prototype中定义共享的属性,这里是一个方法。

引用
The prototype object is associated with the constructor, and each object initialized by the constructor inherits exactly the same set of properties from the prototype. This means that the prototype object is an ideal place for methods and other constant properties.


在新建一个对象时,构造函数和Prototype对象共同作用。每个对象都会从Prototype中继承属性。我们可以将对象的常量和方法放在对象的Prototype里面。

引用

Inherited properties behave just like regular properties of an object. They are enumerated by the for/in loop and can be tested with the in operator.


继承过来的属性和普通属性一样,同样可以被for/in的循环中枚举出来。你只能通过对象的hasOwnProperty()方法来辨别:

var r = new Rectangle(2, 3);
r.hasOwnProperty("width");   // true: width is a direct property of r
r.hasOwnProperty("area");    // false: area is an inherited property of r
"area" in r;                 // true: "area" is a property of r


Therefore, property inheritance occurs only when you read property values, not when you write them. If you set the property p in an object o that inherits that property from its prototype, what happens is that you create a new property p directly in o. Now that o has its own property named p, it no longer inherits the value of p from its prototype. 


这种继承是可读的,但不可写。如果你试图修改对象中某个通过Prototype继承过来的属性,操作是可以完成的,结果是这个对象自己拥有了一个赋有新值的属性,它再也不继承自Prototype。

Extending Built-in Types
扩展内置的数据类型

// Returns true if the last character is c
String.prototype.endsWith = function(c) {
    return (c == this.charAt(this.length-1))
}

var message = "hello world";
message.endsWith('h')  // Returns false
message.endsWith('d')  // Returns true

引用

There is a strong argument against extending built-in types with your own methods; if you do so, you are essentially creating your own custom version of the core JavaScript API. Any other programmers who have to read or maintain your code will likely find it confusing if your code includes methods they have never heard of.

Note that you must never add properties to Object.prototype.

The technique shown here for extending built-in object types is guaranteed to work only for core JavaScript "native objects
."

There is one case in which it is safe and useful to extend the prototype of a built-in native class: to add standard methods to a prototype when an old or incompatible JavaScript implementation lacks them.


扩展JS内核的数据类型是十分具有争议的行为。例如上例中,我们扩展类String的内置方法,可是这样就相当于自定了JS的API,其他程序员不可能知道你的制定的这些特性。除非你想开发JS的大型框架。

另外,不要试图去扩展Object,这太危险了。JS的每个对象都从Object继承。如果你真的修改了Object的Prototype,那么用{}字面量新建的对象也是默认包含那些属性的,而不是我们预期中的“空”。

扩展核心API当然也可以来弥补兼容性的不足。
例如,IE4&5都不支持Function.apply()方法,那么我们可以定义它:
// IE 4 & 5 don't implement Function.apply( ).
// This workaround is based on code by Aaron Boodman.
if (!Function.prototype.apply) {
    // Invoke this function as a method of the specified object,
    // passing the specified parameters.  We have to use eval( ) to do this
    Function.prototype.apply = function(object, parameters) {
        var f = this;                // The function to invoke
        var o = object || window;    // The object to invoke it on
        var args = parameters || []; // The arguments to pass

        // Temporarily make the function into a method of o
        // To do this we use a property name that is unlikely to exist
        o._$_apply_$_ = f;

        // We will use eval( ) to invoke the method. To do this we've got
        // to write the invocation as a string. First build the argument list.
        var stringArgs = [];
        for(var i = 0; i < args.length; i++)
            stringArgs[i] = "args[" + i + "]";

        // Concatenate the argument strings into a comma-separated list.
        var arglist = stringArgs.join(",");

        // Now build the entire method call string
        var methodcall = "o._$_apply_$_(" + arglist + ");";

        // Use the eval( ) function to make the methodcall
        var result = eval(methodcall);

        // Unbind the function from the object
        delete o._$_apply_$_;

        // And return the result
        return result;
    };
}

分享到:
评论
4 楼 robinqu 2010-08-26  
truth315 写道
不好意思了,compu指的是getArea,粘贴过来时忘记改了.
不过在IE8,Firefox3.6,chrome都是可以运行的哦


那我搞错了~这里会作为对象的方法的运行,所以this还是指向该对象吧?
我没有去些demo~

可以考虑把这些方法写在一个对象下面,然后直接将该对象合并到需要这些方法的“类“的prototype里面。
3 楼 truth315 2010-08-25  
不好意思了,compu指的是getArea,粘贴过来时忘记改了.
不过在IE8,Firefox3.6,chrome都是可以运行的哦
2 楼 robinqu 2010-08-22  
truth315 写道
function Rectangle(w, h) {
    this.width = w;
    this.height = h;
    this.area = function( ) { return this.width * this.height; }
}

"以这种常规属性来存储对象方法是很没有效率的,这种方法本该是没个这样的对象实例所“共享”的,而不要每次新建一个对象都要新建一个这个方法的拷贝。"

如果代码是如下的样子:
function getArea(){
	return this.width * this.height;
}

function Rectangle(w, h) {
    this.width = w;
    this.height = h;
    this.area = compu;
}

会不会也导致“存储对象方法是很没有效率”?求答复



不明白第二段代码的第8行,compu是啥?如果你指的是
this.area = getArea;
你会悲剧的发现这个代码会报错的。
全局函数的this指向的是window对象⋯⋯

如果你的思想是把所有方法做成公共的全局函数,也是不错的,就是你在对象构造的时候比较麻烦,必须每个每个添加那些方法⋯⋯
1 楼 truth315 2010-08-21  
function Rectangle(w, h) {
    this.width = w;
    this.height = h;
    this.area = function( ) { return this.width * this.height; }
}

"以这种常规属性来存储对象方法是很没有效率的,这种方法本该是没个这样的对象实例所“共享”的,而不要每次新建一个对象都要新建一个这个方法的拷贝。"

如果代码是如下的样子:
function getArea(){
	return this.width * this.height;
}

function Rectangle(w, h) {
    this.width = w;
    this.height = h;
    this.area = compu;
}

会不会也导致“存储对象方法是很没有效率”?求答复

相关推荐

    JavaScript的prototype

    JavaScript的`prototype`机制是其面向对象编程的基础,它允许对象间共享方法,实现继承。理解并熟练掌握`prototype`,对于编写高效、可维护的JavaScript代码至关重要。通过`prototype`,开发者可以构建复杂的应用...

    javascript类库prototype.js

    这个库的设计理念是扩展JavaScript的基础对象,提供一套统一且易于使用的API,从而简化前端开发工作。 Prototype.js 的核心特性: 1. **对象扩展**:Prototype.js 最显著的特点是对JavaScript原生对象的扩展。例如...

    Advanced JavaScript (closures,prototype,inheritance)

    JavaScript,作为一种广泛应用于Web开发的脚本语言,其高级特性如闭包(closures)、原型(prototype)和继承(inheritance)是理解其精髓的关键。本文将深入探讨这些概念,帮助开发者更好地掌握JavaScript的核心。 ...

    javascript prototype文档.rar

    JavaScript中的原型(Prototype)是理解JavaScript继承机制的关键概念。它是一种对象属性,允许一个对象访问并继承另一个对象的属性和方法。在这个“javascript prototype文档”中,我们可以期待深入学习JavaScript...

    JavaScript_Prototype(源代码+中文手册).rar

    原型是JavaScript实现对象继承的基础,它允许一个对象可以继承另一个对象的属性和方法。在JavaScript中,每个对象都有一个特殊的内部属性[[Prototype]],通常通过`__proto__`或`Object.getPrototypeOf`来访问。 1. ...

    javascript prototype原型操作笔记.docx

    #### 一、Prototype基础概念 **Prototype** 在 JavaScript 中是一个非常重要的概念,它支持面向对象编程中的继承特性。每个 JavaScript 对象都有一个内部属性 `[[Prototype]]`,它链接到另一个对象,即原型对象。当...

    Prototype_1.6 JavaScript代码和中文帮助手册

     prototype.js是一个非常优雅的javascript基础类库,对javascript做了大量的扩展,而且很好的支持Ajax,国外有多个基于此类库实现的效果库,也做得很棒。  prototype.js不仅是一个有很大实用价值的js库,而且有很...

    javascript prototype原型详解(比较基础)

    javascript的prototype原型简单介绍: prototype原型是javascript中特别重要的概念,属于必须要掌握,如果没有良好的掌握的话,进一步用好或者学好js基本是不可能的实现的事情,并且此概念稍有难度,可能对于初次接触...

    Professional JavaScript Frameworks: Prototype,YUI, ExtJS, Dojo and MooTools

    《Professional JavaScript Frameworks: Prototype,YUI, ExtJS, Dojo and MooTools》是关于JavaScript框架的高级编程资源,包含了各种知名框架的源代码,这些框架包括Prototype、YUI(Yahoo! User Interface Library...

    JavaScript prototype属性详解

    JavaScript中的`prototype`属性是面向对象编程的关键特性之一,它关联了函数(特别是构造函数)与实例之间的继承关系。...理解并掌握`prototype`的工作原理是深入学习JavaScript面向对象编程的基础。

    JavaScript使用prototype定义对象类型

    在 JavaScript 中,prototype 是一个非常重要的概念,它提供了一套面向对象编程的基础设施,允许开发者定义对象类型和实现继承。下面我们将详细介绍如何使用 prototype 定义对象类型。 一、什么是 Prototype? 在 ...

    JavaScript中prototype的使用

    上述提到的“类型”和“原型”的关系是JavaScript继承的基础。通过设置一个对象的`prototype`为另一个对象,我们可以让这个对象继承另一个对象的属性和方法。例如,如果我们有一个`Point`构造函数,可以将`Point....

    JavaScript 实现基础 ArrayList 功能

    下面将详细介绍如何使用JavaScript来实现基础的ArrayList功能,并探讨在没有参数重载(overload)的情况下如何处理方法的多样性。 首先,我们需要创建一个ArrayList类,这个类将包含添加、删除、查找、更新和遍历...

    Javascript-prototype.js 1.4版开发者手册

    prototype.js是一个非常优雅的javascript基础类库,对javascript做了大量的扩展,而且很好的支持Ajax,国外有多个基于此类库实现的效果库,也做得很棒。 prototype.js不仅是一个有很大实用价值的js库,而且有很高...

    编写基于Prototype的Javascript动画类

    在给定的标题“编写基于Prototype的Javascript动画类”中,我们可以看到讨论的是如何利用Prototype库来创建自定义的动画类。Prototype是一个广泛使用的JavaScript库,它提供了许多便利的功能,包括DOM操作、事件处理...

    JavaScript语言基础知识点总结十张图

    本文将基于“JavaScript语言基础知识点总结十张图”这一主题,深入探讨JavaScript的基础概念、语法特性以及核心知识点。 1. **变量与数据类型** JavaScript有七种数据类型:Undefined、Null、Boolean、Number、...

    JavaScript_prototype_pollution_attack_in_NodeJS.pdf

    **nodejs javascript 前端 prototype 服务端**:这些标签代表了文档涉及的主题范围,即NodeJS(服务器端JavaScript运行时环境)、JavaScript(编程语言)、前端(客户端Web开发)、prototype(原型)和服务端(指...

    JavaScript中的prototype和constructor简明总结

    总结来说,constructor 属性和 prototype 属性在 JavaScript 中非常关键,它们共同构成了 JavaScript 原型继承的基础。理解这两个属性的工作原理对于掌握 JavaScript 面向对象编程及其继承机制至关重要。

Global site tag (gtag.js) - Google Analytics