Nirvana Studio » JavaScript :: 分享知识,传播技术

Archive for the 'JavaScript' Category

JavaScript中的私有成员

Posted by ShiningRay on 2nd 四月 2006

JavaScript中的私有成员

Douglas Crockford www.crockford.com

翻译:ShiningRay @ Nirvana Studio

JavaScript 是世界上最被误解的语言。很多人认为它缺乏信息隐藏的特性所以对象不能有私有实例变量和方法。但这是一个误解。JavaScript对象同样可以拥有私有变量。下面就讲解一下:

对象

JavaScript根本上都是关于的对象(Object)的。数组(Array)是对象,函数(Function)是对象,Object就不说了。那什么是对象?对象是名称-值的配对的集合。名称是字符串,值可以是字符串、数字、布尔值和对象(包括数组和函数)。对象常常实现为哈希表以快速存取值。

如果一个值是函数,我们可以将它视为方法method。当调用一个对象的方法时,this 变量就会被设为该对象。这个方法就可以通过this变量访问实例变量。

对象是由构造器constructor产生的,它是初始化对象的函数。构造器提供了其它语言中类提供的特性,包括静态方法和变量。

公共成员

对象的成员都是 public 公共成员。任何函数都可以访问、修改或者删除这些成员。有两种主要的途径给新的对象加入成员:

构造器中

这个技术一般用来初始化公共实例变量。构造器的this变量是用来向对象添加成员的。

function Container(param) {    this.member = param;}

这样,如果我们构造一个新的对象

var myContainer = new Container('abc');

那么myContainer.member 就会包含‘abc’

原型中

这个技巧一般用来添加公共方法。当一个成员被检索且没有在对象中发现的时候,那么它就会从对象构造器的 prototype 成员中去获取它。这个原型机制可用来实现继承。它也保存内存。要为一个构造器生成的所有对象加入一个方法,将函数加入构造器的prototype 中:

Container.prototype.stamp = function (string) {
	return this.member + string;
}

这样,我们可以调用这个方法

myContainer.stamp('def')

它会返回‘abcdef’.

私有成员

私有Private成员要由构造器生成。构造器中的普通的var变量和参数都成为私有成员。

function Container(param) {
	this.member = param;
    var secret = 3;
    var self = this;}

这个构造器有三个私有实例变量:param, secret, 和 self。它们被附加到了对象上,但它们无法从外部访问,同时它们也无法被这个对象的公共方法所访问。他们只对私有成员可见。私有方法则是构造器内部的函数。

function Container(param) {

	function dec() {
		if (secret > 0) {
			secret -= 1;
			return true;
		} else {
			return false;
		}
	}

	this.member = param;
	var secret = 3;
	var self = this;
}

私有方法 dec 检查 secret 实例变量。如果它大于0,就减少secret 的大小并返回 true 。否则它返回 false 。这个可以限制对象使用三次。

按照惯例,我们给出一个私有的 self 参数。这个可以令对象对私有方法可见。这种做法是因为ECMAScript Language Specification中的一个错误,这个错误令 this 不能正确地对内部函数设置。

私有方法无法被公共方法调用。要令私有方法有用,我们需要引入一种特权方法。

特权成员

一个特权A privileged 方法可以访问私有的变量和方法,同时它对公共域可见。也可以删除或替换一个特权方法,但不能改变它。

特权方法是用 this 在构造器中分配的。

function Container(param) {

	function dec() {
		if (secret > 0) {
			secret -= 1;
			return true;
		} else {
			return false;
		}
	}

	this.member = param;
	var secret = 3;
	var self = this;

	this.service = function () {
		if (dec()) {
			return self.member;
		} else {
			return null;
		}
	};
}

service 就是一个特权方法。前三次调用会返回‘abc’
之后 ,它会返回 nullservice调用的私有的 dec 方法,而
dec又访问了私有的 secret变量。service对其它的对象和方法是可见的,但不能直接访问私有成员。

闭包

这种公共、私有和特权成员的模式是可行的原因是由于JavaScript有 closure闭包。这个意味着一个内部的函数总是可以访问这个函数外部的变量和参数,甚至在外部的函数返回之后。这是这个语言的一个极其强大的特性。目前没有哪本关于JavaScript编程的书展示了如何发掘这个特性。大多数都没有提到。

私有和特权成员只能在对象构造的时候生成。公共成员可以在任意时刻添加。

模式

公共(Public)

function Constructor(…) {
	this.membername = value;
}
Constructor.prototype.membername = value;

私有(Private)

function Constructor(…) {
	var self =  this;
	var membername =  value;
	function  membername(…)  {…}
}

注意,实际上函数语句

function  membername(…)  {…}

是以下语句的缩写,两者相同:

var  membername = function  membername(…)  {…};

特权(Privileged)

function Constructor(…) {
	this.membername =  function (…)  {…};
}

Copyright 2001 Douglas Crockford. All Rights Reserved Wrrrldwide.

Posted in JavaScript | 4 Comments »

JavaScript:世界上最被误解的语言

Posted by ShiningRay on 2nd 四月 2006

JavaScript:
世界上最被误解的语言

Douglas Crockford
www.crockford.com

原文地址:JavaScript: The Wrrrld’s Most Misunderstood Programming Language  

翻译:ShiningRay
http://www.nirvanastudio.org/

JavaScript,
亦称为 Mocha、LiveScript,也叫做JScript ECMAScript,是世界上流行的编程语言之一。事实上世界上差不多每台个人电脑都至少安装了一个JavaScript解释器。JavaScript的流行完全在于它作为WWW的脚本语言的角色。

不管它有多么流行,极少有人了解JavaScript是一个十分动态的通用面向对象编程语言。这怎能成为一个秘密呢?为什么这个语言如此被误解?

关于名字

这个Java-前缀暗示了JavaScript和Java的关系,也就是JavaScipt是Java的一个子集也就是不如Java强大。看上去这个名称就故意制造混乱,然后随之而来的是误解。JavaScript并不是解释型的Java语言。Java是解释型的Java,JavaScript是另一种语言。

JavaScript和Java的语法很相似,就象Java和C的语法相似一样。但它也不是Java的子集就像Java也不是C的子集一样。在应用上,Java要远比原先设想的好得多(Java原称Oak)。

JavaScript并不是由Sun公司──Java的老家──开发的。JavaScript是由Netscape公司开发。它本来叫做LiveScript,这个名字并不是那样容易混淆。

这个-Script
后缀暗示了它不是一个真正的编程语言──脚本语言好象不是真正的编程语言。但其实这是一个专长的问题。相对C而言,JavaScript牺牲性能但带来更强的表达力和动态性。

披着C外衣的Lisp

JavaScript的C风格的语法,包括大括号和复杂的for
语句,让它看起来好象是一个普通的过程式语言。这是一个误导因为JavaScript和函数式语言如Lisp和Scheme有更多的共同之处。它用数组代替了列表,用对象代替了属性列表。函数是第一型的。而且有闭包。你不需要平衡那些括号就可以用lambda算子。

思维定势

JavaScript是原被设计在Netscape Navigator 中运行的。它的成功让它成为几乎所有浏览器的标准配置。这导致了思维定势。JavaScript简直就是程序语言中的George Reeves (一位曾扮演超人的演员,但后来死于枪杀,被官方认为自杀,细节不详──译注)。其实,JavaScript也适合很多和Web无关的应用程序。

不断改变的目标

JavaScript的第一个版本功能十分弱。它缺少异常处理、内部函数和继承。而它的现在的形态,它已经是一套完整的面向对象语言。但很多看法都是基于认为它的形式不成熟。

管理这个语言的ECMA委员正在开发扩展 ,原意是很好,而这样却会加剧这个语言最严重的问题:版本太多了。这也造成了混淆。

设计错误

没有什么编程语言是完美的,JavaScript也有它的设计上的错误,如的重载同时表示加和带类型转换的串连接,和有错误倾向的
with
语句应该避免使用。保留字策略过于严格。分号的加入是一个很大的错误,正则表达式的记号也是。这些错误会导致编程错误,并把语言的设计作为整个叫做问题。幸运的是,这些问题可以用一个很好lint程序来避免。

这个语言的设计从整体上看还是十分健全的。但很令人惊讶的是,
ECMAScript委员会好象根本不想修正这些错误。也许他们对重新制作一个更感兴趣。

肮脏的实现

JavaScript早期实现错误百出。这对该语言带来了很恶劣的影响。更糟糕的是,这些实现还被嵌入的更错误百出的浏览器中。

拙劣的书籍

几乎所有的书籍都十分恐怖。里面到处是错误、蹩脚的例子还自创一套拙劣的惯例。语言中重要的特性却常常解释不好,或者干脆完全不写。我翻阅了几十本JavaScript的书,我只推荐两本:JavaScript:
The Definitive Guide (4th Edition)
by David Flanagan and
Dynamic
HTML (2nd Edition)
by Danny Goodman. 都来自于
O’Reilly.

不够标准的标准

该语言的官方标准规格说明书由ECMA发布。该规格书也是质量奇差。它难以阅读也难以理解。它也对拙劣书籍的问题作出了自己的一份“贡献”,因为作者无法使用这个标准文档来增加他们对语言的认识。ECMA和TC39委员会应该为此感到深深的羞愧。

业余爱好者

大部分写JavaScript的人都不是程序员。他们缺乏训练写好程序的修养。JavaScript有如此丰富的表达能力,他们可以任意用它来写代码,以任何形式。这给JavaScript带来了一个名声──它是专门为外行设计的,不适合专业的程序员。这显然不是事实。

面向对象

JavaScript是不是面向对象的?它拥有对象,可以包含数据和处理数据的方法。对象可以包含其它对象。它没有类,但它却有构造器可以做类能做的事,包括扮演类变量和方法的容器的角色。它没有基于类的继承,但它有基于原型的继承。

两个建立对象系统的方法是通过继承(是一个……)和通过聚合(有一个……)。JavaScript两个都有,但它的动态性质让它可以在聚合上超越。

一些批评说JavaScript不是真正面向对象的因为它不能提供信息的隐藏。也就是,对象不能有私有变量和私有方法:所有的成员都是公共的。S

但又有证明了JavaScript对象可以拥有私有变量和私有方法。当然,极少有人认识到,因为JavaScript是世界是最受误解的程序嘛!

另外还有批评说JavaScript不能提供继承,这里证明了JavaScript不仅能支持传统的继承还能应用其它的代码复用模式

Copyright 2001 Douglas
Crockford.
All
Rights Reserved Wrrrldwide.

Posted in JavaScript | 9 Comments »