var a = 'global';
(function () {
alert(a);
var a = 'local';
})();
大家第一眼看到这个例子觉得输出结果是什么?‘global’?还是‘local’?其实都不是,输出的是undefined,不用迷惑,我的题外话就是为了讲这个东西的。
其实很简单,看一看JavaScript运行机制就会明白。我们可以把这种现象看做“预声明”。但是如果稍微深究一下,会明白得更透彻。
这里其实涉及到对象属性绑定机制。因为所有JavaScript函数都是一个对象。在函数里声明的变量可以看做这个对象的“类似属性”。对象属性的绑定在语言里是有分“早绑定”和“晚绑定”之分的。
早绑定
是指在实例化对象之前定义其属性和方法。解析程序时可以提前转换为机器代码。通常的强类型语言如C++,java等,都是早绑定机制的。而JavaScript不是强类型语言。它使用的是“晚绑定”机制。
晚绑定
是指在程序运行前,无需检查对象类型,只要检查对象是否支持特性和方法即可。可以在绑定前对对象执行大量 *** 作而不受任何惩罚。
上面代码出现的“预声明”现象,我们大可用“晚绑定”机制来解释。在函数的作用域中,所有变量都是“晚绑定”的。 即声明是顶级的。所以上面的代码和下面的一致:
var a = 'global';
(function () {
var a;
alert(a);
a = 'local';
})();
在alert(a)之前只对a作了声明而没有赋值。所以结果可想而知。
<!-- 题外话到此结束 -->
RT:本文要说的是,在JavaScript里,我所知道的几种定义类和对象的方式:<! -- 声明:以下内容大部分来自《JavaScript高级程序设计》,只是个人叙述方式不同而已 -- >
直接量方式
使用直接量构建对象是最基础的方式,但也有很多弊端。
var Obj = new Object;
Objname = 'sun';
ObjshowName = function() {
alert('thisname');
}
我们构建了一个对象Obj,它有一个属性name,一个方法showName。但是如果我们要再构建一个类似的对象呢?难道还要再重复一遍?
NO!,我们可以用一个返回特定类型对象的工厂函数来实现。就像工厂一样,流水线的输出我们要的特定类型结果。
工厂方式
function createObj(name) {
var tempObj = new Object;
tempObjname = name;
tempObjshowName = function () {
alert(thisname);
};
return tempObj;
}
var obj1 = createObj('obj_one');
var obj2 = createObj('obj_two');
这种工厂函数很多人是不把他当做构建对象的一种形式的。一部分原因是语义:即它并不像使用了运算符new来构建的那么正规。还有一个更大的原因,是因为这个工厂每次产出一个对象都会创建一个新函数showName(),即每个对象拥有不同的版本,但实际上他们共享的是同一个函数。
有些人把showName在工厂函数外定义,然后通过属性指向该方法,可以避开这个问题:
代码
可惜的是,这种方式让showName()这个函数看起来不像对象的一个方法。
构造函数方式
这种方式是为了解决上面工厂函数的第一个问题,即没有new运算符的问题。可是第二个问题它依然不能解决。我们来看看。
function Obj(name) {
thisname = name;
thisshowName = function () {
alert(thisname);
}
}
var obj1 = new Obj('obj_one');
var obj2 = new Obj('obj_two');
它的好处是不用在构造函数内新建一个对象了,因为new运算符执行的时候会自动创建一个对象,并且只有通过this才能访问这个对象。所以我们可以直接通过this来对这个对象进行赋值。而且不用再return,因为this指向默认为构造函数的返回值。
同时,用了new关键字来创建我们想要的对象是不是感觉更“正式”了。
可惜,它仍然不能解决会重复生成方法函数的问题,这个情况和工厂函数一样。
原型方式
这种方式对比以上方式,有个很大的优势,就是它解决了方法函数会被生成多次的问题。它利用了对象的prototype属性。我们依赖原型可以重写对象实例。
var Obj = function () {}
Objprototypename = 'me';
ObjprototypeshowName = function () {
alert(thisname);
}
var obj1 = new Obj();
var obj2 = new Obj();
我们依赖原型对构造函数进行重写,无论是属性还是方法都是通过原型引用的方式给新建的对象,因此都只会被创建一次。可惜的是,这种方式存在两个致命的问题:
1。没办法在构建对象的时候就写入想要的属性,因为原型在构造函数作用域外边,没办法通过传递参数的方式在对象创建的时候就写入属性值。只能在对象创建完毕后对值进行重写。
2。致命问题在于当属性指向对象时,这个对象会被多个实例所共享。考虑下面的代码:
var Obj = function () {}
Objprototypename = 'me';
Objprototypeflag = new Array('A', 'B');
ObjprototypeshowName = function () {
alert(thisname);
}
var obj1 = new Obj();
var obj2 = new Obj();
obj1flagpush('C');
alert(obj1flag); // A,B,C
alert(obj2flag); //A,B,C
是的,当flag属性指向对象时,那么实例obj1和obj2都共享它,哪怕我们仅仅改变了obj1的flag属性,但是它的改变在实例obj2中任然可见。
面对这个问题,让我们不得不想是否应该把构造函数方式和原型方式结合起来,让他们互补。。。
构造函数和原型混合方式
我们让属性用构造函数方式创建,方法用原型方式创建即可:
var Obj = function (name) {
thisname = name;
thisflag = new Array('A', 'B');
}
Objprototype = {
showName : function () {
alert(thisname);
}
}
var obj1 = new Obj();
var obj2 = new Obj();
obj1flagpush('C');
alert(obj1flag); // A,B,C
alert(obj2flag); //A,B
这种方式有效地结合了原型和构造函数的优势,是目前用的最多,也是副作用最少的方式。
不过,有些追求完美的家伙还不满足,因为在视觉上还没达到他们的要求,因为通过原型来创建方法的过程在视觉上还是会让人觉得它不太像实例的方法(尤其对于传统OOP语言的开发者来说。)
所以,我们可以让原型活动起来,让他也加入到构造函数里面去,好让这个构造函数在视觉上更为统一。而这一系列的过程只需用一个判断即可完成。
var Obj = function (name) {
thisname = name;
thisflag = new Array('A', 'B');
if (typeof Obj_init == 'undefined') {
Objprototype = {
showName : function () {
alert(thisname);
}
};
Obj_init = true;
}
}
如上,用_init作为一个标志来判断是否已经给原型创建了方法。如果是那么就不再执行。这样其实在本质上是没有任何变化的,方法仍是通过原型创建,唯一的区别在于这个构造函数看起来“江山统一”了。
但是这种动态原型的方式是有问题的,《JavaScript高级程序设计》里并没有深究。创建第一个对象的时候会因为prototype在对象实例化之前没来的及建起来,是根本无法访问的。所以第一个对象是无法访问原型方法的。同时这种方式在子类继承中也会有问题。
关于解决方案,我会在下一文中说明。
其实就使用方便来说的话,个人觉得是没必要做这个判断的。。。呵呵 ^_^在整个文件中的JavaScript参数并不全局工作nodejs中你需要将它们传递给函数。//startjsconstROOT_DIR=__dirname;constAPP_DIR=ROOT_DIR+'/app/';constMODULES_DIR='/usr/local/lib/node_modules/';constAPP_PORT=4935;varserver=require(APP_DIR+'serverjs');serverstart(MODULES_DIR,APP_PORT,ROOT_DIR);//serverjsexportsstart=function(MODULES_DIR,APP_PORT,ROOT_DIR){varexpress=require(MODULES_DIR+'express'),app=express(),>
js中有六种数据类型,包括五种基本数据类型(Number,String,Boolean,Undefined,Null),和一种复杂数据类型(Object)。
1、Number类型
Number类型包含整数和浮点数(浮点数数值必须包含一个小数点,且小数点后面至少有一位数字)两种值。
2、String类型
在JS中字符串需要使用引号引起来。使用双引号或单引号都行,但是不要混着用。引号不能嵌套,双引号不能放双引号,单引号不能放单引号。
3、Boolean类型
该类型只有两个值,true和false。
4、Undefined类型
只有一个值,即undefined值。使用var声明了变量,但未给变量初始化值,那么这个变量的值就是undefined。
5、Null类型
null类型被看做空对象指针,null类型也是空的对象引用。
6、Object类型
js中对象是一组属性与方法的集合。这里就要说到引用类型了,引用类型是一种数据结构,用于将数据和功能组织在一起。引用类型有时候也被称为对象定义,因为它们描述的是一类对象所具有的属性和方法。
其实简单来说,原型就是一个对象对另一个对象的引用。
然后其是怎么联系起来的呢,是通过prototype。对就是这个,给你一个例子
var obj = {a: 2
}
var myObj = Objectcreate(obj);
consolelog(myObja); // 2
consolelog(myObj === obj); // false
consolelog(ObjectgetPrototypeOf(myObj) === obj); // true
ObjectgetPrototypeOf(myObj)a = 4
consolelog(obja); // 4
通过上面的例子,你可以看到,myObj的原型就是obj!然后obj的原型是哪个呢,是Objectprototype。实际上通过上面,你就能知道,原型原理上是对于另一个对象的引用,通过引用吧几个对象给串联起来调用。
那么你的第二个问题马上又来了,可能也是你关心的问题,类和原型的关系是啥呢?
实际上,类在实例化的时候,也就是通过new来创建一个对象的时候,是分为以下几步的:
创建一个全新的对象
这个新对象会被执行prototype连接
新对象绑定到函数调用的this
如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象
这个就是new实例化的时候,所做的一些步骤,那么你其中有几个需要注意的点:
如果有return并且返回的是一个对象的话,则直接返回return后的那个对象。
反之,则新建一个对象。
并且吧函数的prototype引用到新建对象的prototype中。
这个怎么理解呢?再给你一个例子,可能例子更直观一些:
b: 10
}
function Foo() {}
Fooprototype = protoObj;
var a = new Foo();
consolelog(ObjectgetPrototypeOf(a) === Fooprototype); // true
consolelog(ObjectgetPrototypeOf(a) === protoObj); // true
consolelog(ab); // 10
通过这个例子,你可以看出来,实际上类实例化的过程,其中有一项,就是把其构造好的对象的prototype和类的prototype做关联。因为做好了引用关联,所以构造好的对象可以使用原类里面的原型方法。
这个也讲完了,那么你可能会对class比较感兴趣,想知道class是怎么做的,实际上,class更多,我理解上就是上面类似于Foo()类的一种语法糖,当然也不仅仅是语法糖,但是大体原理是没啥区别的,所以,上面所说的,对于class也同样适用
好啦,如果你对原型和类实例化有更多想了解的,可以给你两篇文章,参考一下:
Javascript基础之-原型(prototype)
Javascript基础之-this
建议在window下,把下面代码保存为 hta 文件以便查看测试。(以下代码在windows7 下测试通过)<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 10 Transitional//EN" "
<html xmlns="
<head runat="server">
<title>JS调用VBS</title>
<HEAD>
<Script language="VBScript">
Class Class_A
Dim test
Sub func()
test = 0
End Sub
End Class
Sub funcX(callback)
Set objC = new Class_A
callback(objC)
End Sub
Set objA= new Class_A
'问题一:这样才算是创建了 vbs 类,下面在js中是不可以直接创建的
</Script>
</HEAD>
<BODY>
<Script language="JavaScript">
alert(objA)//有输出 [object]
// var objA = new Class_A();
//想在这里new一个Class_A的对象,为什么会报Class_A未定义啊?(问题一)
//如果VB里面把这个类的对象定义了之后传给JS:
var objB = new Object();
var callback = function(code) {
objB = code;
documentwrite(objB)
//在js中输出
};
funcX(callback);
//通过上面这个函数,就可以把Class_A的对象给传出来,但是这么做对吗?(问题二)
//这个是可以的
//但是这样创建的对象和JS自己本身的object对象是一种东西不?(问题三)貌似我去调用这个objB的hasOwnProperty属性会报错。
//这个我没有深入研究。。。
</Script>
</BODY>
</html>
js中的类通过function进行定义,使用时,直接new 函数名就是一个类定义。
举例
function TestClass(){thisa='2';
thiskk = function show(){
alert('3');
}
}
var tc = new TestClass();//实例化class
alert(tca);//访问class的属性
alert(tckk());//访问方法
你的代码可以通过如下
var tc = new a();tcc('测试');
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)