JavaScript中的this,prototype与函数原型

JavaScript 函数调用

JavaScript 函数有 4 种调用方式。
每种方式的不同方式在于 this 的初始化。

this 关键字

一般而言,在Javascript中,this指向函数执行时的当前对象。
注意 this 是保留关键字,你不能修改 this 的值。

全局对象

当函数没有被自身的对象调用时, this 的值就会变成全局对象。
在 web 浏览器中全局对象是浏览器窗口(window 对象)。
该实例返回 this 的值是 window 对象。

1.作为一个函数调用

function myFunction(a, b) {
    return a * b;
}
myFunction(10, 2); // myFunction(10, 2) 返回 20

2.函数作为方法调用

var myObject = {
    firstName:"John",
    lastName: "Doe",
    fullName: function () {
        return this.firstName + " " + this.lastName;
    }
}
myObject.fullName(); // 返回 "John Doe"

注意:函数作为对象方法调用,会使得 this 的值成为对象本身。

3.使用构造函数调用函数

如果函数调用前使用了 new 关键字, 则是调用了构造函数。

// 构造函数:
function myFunction(arg1, arg2) {
    this.firstName = arg1;
    this.lastName = arg2;
}
// This creates a new object
var x = new myFunction("John","Doe");
x.firstName; // 返回 "John"

构造函数的调用会创建一个新的对象。新对象会继承构造函数的属性和方法。

构造函数中 this 关键字没有任何的值。
this 的值在函数调用时实例化对象(new object)时创建。

4.作为函数方法调用函数

在 JavaScript 中, 函数是对象。JavaScript 函数有它的属性和方法。
call() 和 apply() 是预定义的函数方法。 两个方法可用于调用函数,两个方法的第一个参数必须是对象本身。

Function myObject(){}
function myFunction(a, b) {
    return a * b;
}
myFunction.call(myObject, 10, 2);//返回20
function myFunction(a, b) { return a * b; }
myArray = [10,3];
myFunction.apply(myObject, myArray);//返回30

两个方法都使用了对象本身作为第一个参数。 两者的区别在于第二个参数: apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。
闭包深入:http://www.cnblogs.com/onepixel/p/5062456.html

1.原型法设计模式

在.Net中可以使用clone()来实现原型法
原型法的主要思想是,现在有1个类A,我想要创建一个类B,这个类是以A为原型的,并且能进行扩展。我们称B的原型为A。

2. Javascript的方法可以分为三类:

a.类方法
b.对象方法
c.原型方法

function People(name){
    this.name=name;
    //对象方法
    this.Introduce=function(){
        alert("My name is "+this.name);
    }
}
//类方法
People.Run=function(){
    alert("I can run");
}
//原型方法
People.prototype.IntroduceChinese=function(){
    alert("我的名字是"+this.name);
}

//测试
var p1=new People("Windking");
p1.Introduce();
People.Run();
p1.IntroduceChinese();

prototype是什么含义?
javascript中的每个对象都有prototype属性,Javascript中对象的prototype属性的解释是:返回对象类型原型的引用。
A.prototype = new B();
理解prototype不应把它和继承混淆。A的prototype为B的一个实例,可以理解A将B中的方法和属性全部克隆了一遍。A能使用B的方法和属性。这里强调的是克隆而不是继承。可以出现这种情况:A的prototype是B的实例,同时B的prototype也是A的实例。
先看一个实验的例子:

function baseClass(){
    this.showMsg = function(){
        alert("baseClass::showMsg");
    }
}
function extendClass(){}
extendClass.prototype = new baseClass();
var instance = new extendClass();
instance.showMsg(); // 显示baseClass::showMsg

我们首先定义了baseClass类,然后我们要定义extentClass,但是我们打算以baseClass的一个实例为原型,来克隆的extendClass也同时包含showMsg这个对象方法。
extendClass.prototype = new baseClass()就可以阅读为:extendClass是以baseClass的一个实例为原型克隆创建的。
那么就会有一个问题,如果extendClass中本身包含有一个与baseClass的方法同名的方法会怎么样?
下面是扩展实验2:

function baseClass(){
    this.showMsg = function(){
        alert("baseClass::showMsg");
    }
}
function extendClass(){
    this.showMsg =function (){
        alert("extendClass::showMsg");
    }
}
extendClass.prototype = new baseClass();
var instance = new extendClass();
instance.showMsg();//显示extendClass::showMsg

实验证明:函数运行时会先去本体的函数中去找,如果找到则运行,找不到则去prototype中寻找函数。或者可以理解为prototype不会克隆同名函数。
那么又会有一个新的问题:
如果我想使用extendClass的一个实例instance调用baseClass的对象方法showMsg怎么办?

3. obj1.func.call(obj)方法

意思是将obj看成obj1,调用func方法
答案是可以使用call:

extendClass.prototype = new baseClass();
var instance = new extendClass();
var baseinstance = new baseClass();
baseinstance.showMsg.call(instance);//显示baseClass::showMsg

这里的baseinstance.showMsg.call(instance);阅读为“将instance当做baseinstance来调用,调用它的对象方法showMsg”
好了,这里可能有人会问,为什么不用baseClass.showMsg.call(instance);
这就是对象方法和类方法的区别,我们想调用的是baseClass的对象方法
最后,下面这个代码如果理解清晰,那么这篇文章说的就已经理解了:

function baseClass(){
    this.showMsg = function(){
        alert("baseClass::showMsg");  
    }
    
    this.baseShowMsg = function(){
        alert("baseClass::baseShowMsg");
    }
}
baseClass.showMsg = function(){
    alert("baseClass::showMsg static");
}
function extendClass(){
    this.showMsg =function (){
        alert("extendClass::showMsg");
    }
}
extendClass.showMsg = function(){
    alert("extendClass::showMsg static")
}
extendClass.prototype = new baseClass();
var instance = new extendClass();
instance.showMsg(); //显示extendClass::showMsg
instance.baseShowMsg(); //显示baseClass::baseShowMsg
instance.showMsg(); //显示extendClass::showMsg
baseClass.showMsg.call(instance);//显示baseClass::showMsg static
var baseinstance = new baseClass();
baseinstance.showMsg.call(instance);//显示baseClass::showMsg

转载于 http://www.cnblogs.com/yjf512/archive/2011/06/03/2071914.html

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Captcha Code