关于Object-Oritented Javascript

来源:互联网 发布:ubuntu需要多大空间 编辑:程序博客网 时间:2024/04/30 14:46

关于javascript,,首先,我们得知道三个概念,基本OOP概念:Scope,Cloures,Context( 作用于,闭包,上下文)。对于OOP的应用,则需要知道 Constructors,Method( Public ,private,Privileged).

以上,内容由于时间关系,暂时不整理,今天主要记录一下遇到得问题。



Q1:关于构造函数的三部曲。有如下一个构造函数,


var User = function (name) {  this.name = name;  function welcome () {    alert( “Welcome back, ” +this.name + “.”);  }  welcome();}


 
var me = new User( “Bob” );  // Alerts: “Welcome, Bob.”


要创建一个me实例,必须使用new操作符,以这种方式调用构造函数会经历如下三个步骤;
(1)创建一个空对象,并且this变量引用了该对象,同时还继承了该函数的原型。
(2)将构造函数的作用域赋给新对象,属性和方法被加入到This引用的对象中。
(3)新创建的对象由this所引用,最终隐式的返回this。

也就是

var User = function (name) {
  var this = {}; //步骤(1)
this.constructor = User; //步骤(2)
// function body。。

return this;// 步骤(3)

}
我今天试图将构造函数的返回值手动设置为一个特权方法
var User = function (name) {
   this.name = name;

  function welcome () {
     alert( “Welcome back, ” +this.name + “.”);
  }

  return {welcome:welcome}
}

事实上这样的话,当你new一个对象时,调用welcome(),并不能打印出this.name; this.name = undefined, 这就是因为,函数最终的返回值并不是this,当你想要访问该构造函数的属性时,它将是没有定义的。
需要注意一点:上面所说的“ 空对象”其实并不空,它已经从User的原型中继承了许多成员,因此它更像是下面的语句:var this = Object.create( User.prototype).
当用New操作符创建对象时,构造函数总是返回一个对象,默认情况下是返回this 所引用的对象。如果在构造函数中并不向this添加人和属性,将返回“空对象”。
我们可以根据需要返回任意的其他的对象,如下面的例子所示,that引用了新创建的对象,并且返回了that所引用的对象。如果试图返回并非对象的值,函数会忽略该值,相反构造函数还是会返回This引用的这个对象。
var obj = function(){ 
this.name = "this is pp"; 
var that = {};  
that.name = "that is pp";
return that;
}
var o = new obj();
o.name; // "that is pp"


Q2:函数表达式与函数声明的区别;
函数表达式: var fun = function fun(){ }
函数声明:function fun(){ }
当你想在函数体中调用自己本身时,你就必须得用函数表达式了,比如
var user = function User(){var obj = {};obj.constructor =User;return obj;}



Q3:单体模式,使用同一个构造函数以new操作符来创建多个对象时,想获得指向完全相同的对象的新指针。即想得到如下的预期效果
var uni1 = new Universe();
var uni2 = new Universe();
uni1 === uni2;// true
想实现如上效果,有三种方法可以解决。
1,使用全局变量globle来存储该实例。但是,需要知道,过多的全局变量,会使全局环境受到污染。
2,在构造函数的静态属性中缓存该实例。
3.可以将实例包装在一个闭包中。我们知道闭包访问外部函数的变量是通过引用访问。,不过,需要知道的一点是,闭包会带来额外的开销。

下面是一个在Universe构造函数的静态属性中缓存单个实例的例子
。。。。


下面是一个使用闭包来保护单个实例的例子,重点是在重写构造函数。

function Universe(){var instance = this;this.time_s = 0;this.bang = "big";Universe = function (){debuggerreturn instance;}};var uni1 = new Universe();var uni2 = new Universe();uni1 === uni2 // true;


在分析这个例子的时候,需要知道,在闭包里,如果闭包引用了外部函数的变量,外部函数的生命周期并不是在外部函数调用完后就结束,而是在内部闭包结束后,不在引用外部变量了,它的声明周期才结束。也就是说,当第二次new 实例的时候,调用的是里面这个Universe,但是里面的Universe仍然能访问外部函数的instance变量,而且是按引用访问。
在实现上面这种方法的时候,有一个缺点,主要在于重写构造函数会丢失在初始定义和重定义时刻之间添加到它里面的属性。为了解决这个问题,我们需要做如下改动。
function Universe(){var instance; Universe = function Universe(){return instance;}Universe.prototype = this; //外部构造函数产生的实例instance = new Universe(); //instance 并不是Undefined,它继承了父类原型上的属性和方法// instance.constructor = Universe;instance.time_s = 0;instance.bang = "big";return instance; //返回内部Universe的实例,第一次调用的时候new Universe()返回的也是内部Universe的实例。}
测试用例如下:
Universe.prototype.nothing = truetruevar uni = new Universe()undefinedUniverse.prototype.everything = truetruevar uni = new Universe()undefinedvar uni2 = new Universe()undefineduni ===uni2    //他们是相同的实例trueuni.nothing&&uni.everything&&uni2.nothing&&uni2.everything//所有原型属性都起作用trueuni.bang"big"uni.constructor===Universefalse








原创粉丝点击