您的位置:首页 > Web前端 > JavaScript

JS虽然很烂,但是有些事情还是要知道的

2013-04-02 13:42 246 查看
写惯了c,c++ 实在是不喜欢js这种不严谨的语法和prototype的随处可定义以及唯一作用域。

吐槽完毕,笔记如下:

ECMAScript 有 2 种基本类型:原始与引用(class)。

ECMAScript 有 5 种原始类型(primitive type),即 Undefined、Null、Boolean、Number 和 String。

ECMAScript
提供了 typeof 运算符来判断一个值是否在某种类型的范围内。可以用这种运算符判断一个值是否表示一种原始类型:如果它是原始类型,还可以判断它表示哪种原始类型。

对变量或值调用 typeof 运算符将返回下列值之一:

undefined - 如果变量是 Undefined 类型的
boolean - 如果变量是 Boolean 类型的
number - 如果变量是 Number 类型的
string - 如果变量是 String 类型的
object - 如果变量是一种引用类型或 Null 类型的

null
被认为是对象的占位符

undefined
是声明了变量但未对其初始化时赋予该变量的值,null 则用于表示尚未存在的对象

最后一个特殊值是
NaN,表示非数(Not a Number)。

不推荐使用 NaN 值本身。函数 isNaN() 会做得相当好:

alert(isNaN("blue"));  //输出 "true"
alert(isNaN("666"));  //输出 "false"



Object 对象

ECMAScript 中的所有对象都由这个对象继承而来,Object 对象中的所有属性和方法都会出现在其他对象中,所以理解了 Object 对象,就可以更好地理解其他对象。


Object 对象具有下列属性:

constructor对创建对象的函数的引用(指针)。对于 Object 对象,该指针指向原始的 Object() 函数。Prototype对该对象的对象原型的引用。对于所有的对象,它默认返回 Object 对象的一个实例。


Object 对象还具有几个方法:

hasOwnProperty(property)判断对象是否有某个特定的属性。必须用字符串指定该属性。(例如,o.hasOwnProperty("name"))IsPrototypeOf(object)判断该对象是否为另一个对象的原型。PropertyIsEnumerable判断给定的属性是否可以用 for...in 语句进行枚举。ToString()返回对象的原始字符串表示。对于 Object 对象,ECMA-262 没有定义这个值,所以不同的 ECMAScript 实现具有不同的值。ValueOf()返回最适合该对象的原始值。对于许多对象,该方法返回的值都与 ToString() 的返回值相同。


instanceof 运算符

在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 "object"。ECMAScript 引入了另一个 Java 运算符 instanceof 来解决这个问题。

instanceof 运算符与 typeof 运算符相似,用于识别正在处理的对象的类型。与 typeof 方法不同的是,instanceof 方法要求开发者明确地确认对象为某特定类型。例如:

var oStringObject = new String("hello world");
alert(oStringObject instanceof String);	//输出 "true"


这段代码问的是“变量 oStringObject 是否为 String 对象的实例?”oStringObject 的确是 String 对象的实例,因此结果是 "true"。尽管不像 typeof 方法那样灵活,但是在 typeof 方法返回 "object" 的情况下,instanceof 方法还是很有用的。

下表列出了一些特殊情况,以及它们的结果:

表达式
null == undefinedtrue
"NaN" == NaNfalse
5 == NaNfalse
NaN == NaNfalse
NaN != NaNtrue
false == 0true
true == 1true
true == 2false
undefined == 0false
null == 0false
"5" == 5true
全等号由三个等号表示(===),只有在无需类型转换运算数就相等的情况下,才返回 true


arguments 对象

在函数代码中,使用特殊对象 arguments,开发者无需明确指出参数名,就能访问它们


Function 对象(类)

ECMAScript 最令人感兴趣的可能莫过于函数实际上是功能完整的对象。

Function 类可以表示开发者定义的任何函数。

用 Function 类直接创建函数的语法如下:

var function_name = new function(arg1, arg2, ..., argN, function_body)


在上面的形式中,每个 arg 都是一个参数,最后一个参数是函数主体(要执行的代码)。这些参数必须是字符串

记得下面这个函数吗?

function sayHi(sName, sMessage) {
alert("Hello " + sName + sMessage);
}


还可以这样定义它:

var sayHi
=
new Function("sName", "sMessage", "alert(\"Hello \" + sName + sMessage);");


虽然由于字符串的关系,这种形式写起来有些困难,但有助于理解函数只不过是一种引用类型,它们的行为与用 Function 类明确创建的函数行为是相同的。


ECMAScript 只有公用作用域

对 ECMAScript 讨论上面这些作用域几乎毫无意义,因为 ECMAScript 中只存在一种作用域 - 公用作用域。ECMAScript 中的所有对象的所有属性和方法都是公用的。因此,定义自己的类和对象时,必须格外小心。记住,所有属性和方法默认都是公用的!


关键字 this


this 的功能

在 ECMAScript 中,要掌握的最重要的概念之一是关键字 this 的用法,它用在对象的方法中。关键字 this 总是指向调用该方法的对象,例如:

var oCar = new Object;
oCar.color = "red";
oCar.showColor = function() {
alert([code]this.color
);
};

oCar.showColor(); //输出 "red"[/code]


实现继承的方法


对象冒充

所有新属性和新方法都必须在删除了新方法的代码行后定义。否则,可能会覆盖超类的相关属性和方法:

function ClassB(sColor, sName) {
this.newMethod = ClassA;
this.newMethod(sColor);
delete this.newMethod;

this.name = sName;
this.sayName = function () {
alert(this.name);
};
}



call() 方法

call() 方法是与经典的对象冒充方法最相似的方法。它的第一个参数用作 this 的对象。其他参数都直接传递给函数自身。例如:

function sayColor(sPrefix,sSuffix) {
alert(sPrefix + this.color + sSuffix);
};

var obj = new Object();
obj.color = "blue";

sayColor.call(obj, "The color is ", "a very nice color indeed.");


在这个例子中,函数 sayColor() 在对象外定义,即使它不属于任何对象,也可以引用关键字 this。对象 obj 的 color 属性等于 blue。调用 call() 方法时,第一个参数是 obj,说明应该赋予 sayColor() 函数中的 this 关键字值是 obj。第二个和第三个参数是字符串。它们与 sayColor() 函数中的参数 sPrefix 和 sSuffix 匹配,最后生成的消息 "The color is blue, a very nice color indeed." 将被显示出来。

要与继承机制的对象冒充方法一起使用该方法,只需将前三行的赋值、调用和删除代码替换即可:

function ClassB(sColor, sName) {
//this.newMethod = ClassA;
//this.newMethod(color);
//delete this.newMethod;
ClassA.call(this, sColor);

this.name = sName;
this.sayName = function () {
alert(this.name);
};
}

也可以用apply

function ClassB(sColor, sName) {
//this.newMethod = ClassA;
//this.newMethod(color);
//delete this.newMethod;
ClassA.apply(this, arguments);

this.name = sName;
this.sayName = function () {
alert(this.name);
};
}



原型链(prototype chaining)

继承这种形式在 ECMAScript 中原本是用于原型链的。prototype 对象是个模板,要实例化的对象都以这个模板为基础。总而言之,prototype 对象的任何属性和方法都被传递给那个类的所有实例。原型链利用这种功能来实现继承机制。

如果用原型方式重定义前面例子中的类,它们将变为下列形式:

function ClassA() {
}

ClassA.prototype.color = "blue";
ClassA.prototype.sayColor = function () {
alert(this.color);
};

function ClassB() {
}

[code]ClassB.prototype = new ClassA();

混合方式

这种继承方式使用构造函数定义类,并非使用任何原型。对象冒充的主要问题是必须使用构造函数方式,这不是最好的选择。不过如果使用原型链,就无法使用带参数的构造函数了。开发者如何选择呢?答案很简单,两者都用。 代码如下: function ClassA(sColor) { this.color = sColor; } ClassA.prototype.sayColor = function () { alert(this.color); }; function ClassB(sColor, sName) { [code]ClassA.call(this, sColor);

this.name = sName;
}

ClassB.prototype = new ClassA();


ClassB.prototype.sayName = function () {
alert(this.name);
};[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐