javascript活动对象的理解——伪单例模式

在自己研究javascript各种设计模式的过程中,偶然写出的一段代码让自己理解的更深刻了,之所以称之为伪单例模式,是因为这段代码造成的结果很想单例模式,但是实际上是活动对象捣乱所造成的误会。

代码很简单是这样的:

function Person(){
    var money = 0;
    Person.prototype.getMoney = function (){
        return money;
    }
    Person.prototype.addMoney = function (m){
        money += m;
    }
}
var a = new Person();
var b = new Person();
a.addMoney(20);

console.log(a.getMoney());//打印20
console.log(b.getMoney());//打印20

这里有些同学可能会感觉很奇怪了,a和b完全是两个不同的对象,每次new的时候都会把私有变量money初始化成0,为什么a对象使用addMoney()方法后,同时b对象的money也变成20了呢?

这个时候会造成一种假象,就是通过new实例化多个对象的结果都是产生了同一个对象,仿佛就像单例模式那样。

如果你对这个结果感到疑惑就接着看下吧,如果你一眼就看到其中的原因,那你就不用在这里浪费时间咯~

我们从这个构造函数说起,这里我我使用了var来创造一个私有变量money,并在这个构造函数中提供了两个匿名函数给构造函数的原型对象的getMoney和addMoney,即通过闭包的方式来提供对money变量的访问权限,如果你把原型对象的写在外面是访问不到money这个私有变量的。

事实上恰恰因为我这个行为导致了伪单例的发生,我们接下来用图来剖析一下当我们new对象的时候,函数的活动对象发生了怎样的变化。

如果对函数的活动对象、执行环境不太理解,给个传送门http://www.docin.com/p-509501990.html,讲解的十分清楚。

当我们var a = new Person()后,情况是这样的:

实例对象a通过原型链可以调用原型对象中的两个属性指向那两个匿名函数(迷之圆圈),他们在闭包的帮助下访问活动对象一的money属性。此时money属性初始化为0。

当我们var b = new Person()后,情况变成了这样:

现在可以很清楚的看到,真正改变的是原型对象中属性所指向的匿名函数,也就是说现在实例a和实例b通过原型中的访问所访问的money变量都是位于活动对象2中的,活动对象1已经被玩坏后抛弃了。

再看下一句的a.addMoney(20)实际上就是将活动对象2中的money变成了20,这就很明白了,最后他俩getMoney访问到的都是活动对象2里面的money,自然都会返回20了。则就造成了伪单例的效果。

总结要注意的几点:

1,要达成伪单例的效果,必须将构造函数中的变量设为私有变量而不是通过this设置为实力属性,因为那样访问的就不是通过闭包了。

2,给原型对象添加在构造函数内部才能访问私有变量,不明白?还不去好好看闭包!

3,最后所有的对象访问的都是最后new时,构造函数所形成的活动对象,对此有疑问的同学可以交换一下代码执行的顺序,比如改成这样:

var a = new Person();
a.addMoney(20);//写在前面
var b = new Person();

console.log(a.getMoney());//返回0
console.log(b.getMoney());//返回0

这是很自然的,因为被你你添加的20的那个money在活动对象一中,当你创造活动对象2时,实例对象a已经移情别恋了,a和b现在都指向活动对象2了,其中money被初始化成0,不懂得同学多看看图哟。

时间: 2024-12-11 13:50:28

javascript活动对象的理解——伪单例模式的相关文章

javascript系列学习----对象相关概念理解

1.构造函数(相对于面向对象编程语言里面的类) 2.对象实例(它是由构造函数构造出来的对象,使用到关键字 new) 3.this关键字(往往是指我们的对象本身) 下面我们来看一个实例: var Person = function Person(living, age, gender) {     // "this" below is the new object that is being created (i.e. this = new Object();) this.living

谈谈自己对js闭包,执行上下文,作用域链,活动对象AO,变量对象VO的理解

引子:关于闭包什么是闭包呢?  从定义上来看,所有的函数都可以是闭包.当一个函数在调用时,引用了不是自己作用域内定义的变量(通常称其为自由变量),则形成了闭包:闭包是代码块和创建该代码块的上下文中数据的结合. 例子:   function mytest( ){                                var test=10;          return function( ){                  test++;               alert(t

自己理解的javascript 的对象和类理解

首先需要先理解类和对象的意义,我个人理解如下: 类:对象的抽象化: 对象:类的实体: javascript中没有class关键字和类的用法,只能用伪类来做类的,所以要用function来定义累的名字: 如: function myClass(){ this.name="张三"; } 这样myClass方法才能用原型连接 prototype:这样才能扩展此类: 也可以用 new myClass();这个类 javascript中有对象,简单的写法就是 var obj={name:&quo

谈谈我对Javascript中This对象的理解

this 指针的隐式赋值 this总是指向调用该方法的对象: 在事件中,this指向触发这个事件的对象,特殊的是,IE中的attachEvent中的this总是指向全局对象Window: 显示操纵 this 指针 Javascript引擎通过以下两种方式允许我们显式指定this指针指代的对象: 1. 通过new操作符,Javascript引擎会将this指针返回给被赋值的变量. 2. 通过Function.apply或者Function.call或者Function.bind的原型方法,我们可以

谈谈对Javascript构造函数和原型对象的理解

对象,是javascript中非常重要的一个梗,是否能透彻的理解它直接关系到你对整个javascript体系的基础理解,说白了,javascript就是一群对象在搅..(哔!). 常用的几种对象创建模式 使用new关键字创建最基础的对象创建方式,无非就是和其他多数语言一样说的一样:没对象,你new一个呀! var gf = new Object(); gf.name = "tangwei"; gf.bar = "c++"; gf.sayWhat = function

03.JavaScript 面向对象精要--理解对象

JavaScript 面向对象精要--理解对象 尽管JavaScript里有大量内建引用类型,很可能你还是会频繁的创建自己的对象.JavaScript中的对象是动态的. 一.定义属性 当一个属性第1次被添加给对象时JavaScript在对上上调用了一个名为 [[Put]]的内部方法,该方法会在对象上创建一个新节点保存属性,就像 哈希表上第一次添加一个键一样这个操作不仅指定了初始值 也定义了属性的一些特征 1.1 [[Put]]内部方法 [[Put]]在对象上创建一个自有属性 1.2 [[Set]

1--面试总结-js深入理解,对象,原型链,构造函数,执行上下文堆栈,执行上下文,变量对象,活动对象,作用域链,闭包,This

参考一手资料:http://dmitrysoshnikov.com/ecmascript/javascript-the-core/中文翻译版本:https://zhuanlan.zhihu.com/p/32042645 Javascript 是一种单线程编程语言,这意味着它只有一个调用栈,call Stack(调用栈 ,,先入后出) 核心:对象,原型链,构造函数,执行上下文堆栈,执行上下文,变量对象,活动对象,作用域链,闭包,This js原型链? 定义 原型对象也是简单的对象并且可以拥有它们自

JavaScript中的数组与伪数组的区别

在JavaScript中,除了5种原始数据类型之外,其他所有的都是对象,包括函数(Function). 5种原始数据类型: number boolean string null undefined 在这个前提下,咱们再来讨论JavaScript的对象. 1.创建对象 var obj = {}; //种方式创建对象,被称之为对象直接量(Object Literal) var obj = new Object(); // 创建一个空对象,和{}一样 更多创建对象的知识,参见<JavaScript权威

JavaScript 开发进阶:理解 JavaScript 作用域和作用域链

作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理.今天这篇文章对JavaScript作用域和作用域链作简单的介绍,希望能帮助大家更好的学习JavaScript. JavaScript作用域 任何程序设计语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期.在JavaScript中,变量的作用域有全局作用域和局部作用域两种. 1.  全局作用域(Global S