js 学习笔记
来源:互联网 发布:奥特曼格斗进化3mac版 编辑:程序博客网 时间:2024/05/21 22:35
1,eg:var obj = new XX()。obj 由 XX.prototype.constructor 构造,而非 XX 构造。所以 obj.constructor = XX.prototype.constructor 而非 obj.constructor = XX
2,所有函数的参数都是按值传递。
eg:
function setName(obj){
obj.name = "N";
obj = new Object();
obj.name = "G";
}
var person = new Object();
setName(person);
alert(person.name);//"Nicholas"
person 的值 赋给 obj ---------值传递
obj 就为 person 没有进行拷贝------------引用传递
思考:按照这种思考,java中也只有值传递!
3,js 没有块级域
eg:
function aaa(){
for(var i = 0; i < 10; i++) {
}
alert(i);// 10, 依然能够在aaa这个函数里访问到,块级域在js里不存在,会将它的外层域作为变量的存在域。
}
4,闭包中的this对象
var name = "window";
var obj = {
name : "inner obj",
getNameFunc: function(){
return function(){
return this.name;
};
}
};
alert(obj.getFun()()); // "window"
闭包是一种匿名函数,匿名函数的执行环境具有全局性,因此其this对象通常执行window。
obj.getNameFunc()调用返回一个函数。这是个返回的函数,它不在是obj的属性或者方法,此时调用者是window。因此输出是 The Window5,true false
alert(NaN);//NaN
alert(!NaN);//true
alert(!"");true;
6,正则表达式
(1)test
var text = "abcd";
var pattern = /a/gi;
pattern.test(text);
(2)exec
var text = "abcd";
var pattern = /a/gi;
var matches = pattern.exec(text);
alert(matches[0]);
ECMAScript 定义类或对象
1,原始方式var oCar = new Object;oCar.color = "blue";oCar.doors = 4;oCar.mpg = 25;oCar.showColor = function() { alert(this.color);};缺点:创建多个对象不给力。要一个一个赋值。
2,工厂方式
function createCar() { var oTempCar = new Object; oTempCar.color = "blue"; oTempCar.doors = 4; oTempCar.mpg = 25; oTempCar.showColor = function() { alert(this.color); }; return oTempCar;}var oCar1 = createCar();var oCar2 = createCar();
缺点:每创建一个实例都包含一个相同的属性方法。
3,构造函数方式
function Car(sColor,iDoors,iMpg) { this.color = sColor; this.doors = iDoors; this.mpg = iMpg; this.showColor = function() { alert(this.color); };}var oCar1 = new Car("red",4,23);var oCar2 = new Car("blue",3,25);缺点:同工厂方式相同,每创建一个实例都包含一个重复的方法。
4,原型方式
function Car() {}Car.prototype.color = "blue";Car.prototype.doors = 4;Car.prototype.mpg = 25;Car.prototype.showColor = function() { alert(this.color);};var oCar1 = new Car();var oCar2 = new Car();
缺点:1,使用原型方式,不能通过给构造函数传递参数来初始化属性的值。
2,属性指向的是对象,而不是函数时。函数共享不会造成问题,但对象却很少被多个实例共享。
5,混合的构造函数/原型方式
function Car(sColor,iDoors,iMpg) { this.color = sColor; this.doors = iDoors; this.mpg = iMpg; this.drivers = new Array("Mike","John");}Car.prototype.showColor = function() { alert(this.color);};var oCar1 = new Car("red",4,23);var oCar2 = new Car("blue",3,25);oCar1.drivers.push("Bill");alert(oCar1.drivers);//输出 "Mike,John,Bill"alert(oCar2.drivers);//输出 "Mike,John"缺点:本来已经趋近完美了(可以传参,属性不会被共享,方法不重复创建)。唯一缺点,方法不在构造函数内。
6,动态原型方法
function Car(sColor,iDoors,iMpg) { this.color = sColor; this.doors = iDoors; this.mpg = iMpg; this.drivers = new Array("Mike","John"); if (typeof Car._initialized == "undefined") { Car.prototype.showColor = function() { alert(this.color); }; Car._initialized = true; }}
缺点:与混合的构造函数/原型方式 相比,唯一区别是,方法位置被移动过到了构造函数内。
7,混合工厂方式
function Car() { var oTempCar = new Object; oTempCar.color = "blue"; oTempCar.doors = 4; oTempCar.mpg = 25; oTempCar.showColor = function() { alert(this.color); }; return oTempCar;}
缺点:由于在 Car() 构造函数内部调用了 new 运算符,所以将忽略第二个 new 运算符(位于构造函数之外),在构造函数内部创建的对象被传递回变量 car。
这种方式在对象方法的内部管理方面与经典方式有着相同的问题。强烈建议:除非万不得已,还是避免使用这种方式。
推荐使用:
如前所述,目前使用最广泛的是混合的构造函数/原型方式。此外,动态原始方法也很流行,在功能上与构造函数/原型方式等价。可以采用这两种方式中的任何一种。不过不要单独使用经典的构造函数或原型方式,因为这样会给代码引入问题。
8.StringBuffer 实现
function StringBuffer(){ this.arr = new Array(); if (typeof StringBuffer.init == "undefined") { StringBuffer.prototype.append = function(text){ this.arr.push(text); }; StringBuffer.prototype.toString = function(){ return this.arr.join(""); }; StringBuffer.init = true; }; }
ECMAScript 继承机制实现
对象冒充
function ClassA(sColor) { this.color = sColor; this.sayColor = function () { alert(this.color); };}function ClassB(sColor) {}
function ClassB(sColor, sName) { this.newMethod = ClassA; this.newMethod(sColor); delete this.newMethod; this.name = sName; this.sayName = function () { alert(this.name); };}
原理很简单,就是this被冒充为ClassB的实例了,还可以实现多继承哦。
这种还可以用call ,apply实现。
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); };}
原型链(prototype chaining)
function ClassA() {}ClassA.prototype.color = "blue";ClassA.prototype.sayColor = function () { alert(this.color);};function ClassB() {}ClassB.prototype = new ClassA();ClassB.prototype.custructor = ClassB;
注意:调用 ClassA 的构造函数,没有给它传递参数。这在原型链中是标准做法。要确保构造函数没有任何参数。
与对象冒充相似,子类的所有属性和方法都必须出现在 prototype 属性被赋值后,因为在它之前赋值的所有方法都会被删除。为什么?因为 prototype 属性被替换成了新对象,添加了新方法的原始对象将被销毁。所以,为 ClassB 类添加 name 属性和 sayName() 方法的代码如下:
function ClassB() {}ClassB.prototype = new ClassA();ClassB.prototype.name = "";ClassB.prototype.sayName = function () { alert(this.name);};ClassB.prototype.custructor = ClassB;
混合方式(冒充+原型链)
这种继承方式使用构造函数定义类,并非使用任何原型。对象冒充的主要问题是必须使用构造函数方式,这不是最好的选择。不过如果使用原型链,就无法使用带参数的构造函数了。开发者如何选择呢?答案很简单,两者都用。
在前一章,我们曾经讲解过创建类的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承 prototype 对象的方法。用这两种方式重写前面的例子,代码如下:
function ClassA(sColor) { this.color = sColor;}ClassA.prototype.sayColor = function () { alert(this.color);};function ClassB(sColor, sName) { ClassA.call(this, sColor); this.name = sName;}ClassB.prototype = new ClassA();ClassB.prototype.sayName = function () { alert(this.name);};ClassB.prototype.custructor = ClassB;
增加getElementsByClassName方法
function getByClass(oParent,cls){ if (document.getElementsByClassName){ return (oParent || document).getElementsByClassName(cls); }else{ var oParent = oParent || document; var reg= new RegExp("^|\\s"+cls+"$|\\s","i"), res = [], child = null; for (var i = 0; i < oParent.all.length; i ++){ child = oParent.all[i]; if (reg.test(child.className)){ res.push(child); } }; return res; } }
易错:函数中声明的变量在整个函数中都有定义。
首先观察这段代码:
- <script type="text/javascript">
- function rain(){
- var x = 1;
- function man(){
- x = 100;
- }
- man(); //调用man
- alert( x ); //这里会弹出 100
- }
- rain(); //调用rain
- </script>
上面得代码说明了,变量x在整个rain函数体内都可以使用,并可以重新赋值。由于这条规则,会产生“匪夷所思”的结果,观察下面的代码。
- <script type="text/javascript">
- var x = 1;
- function rain(){
- alert( x ); //弹出 'undefined',而不是1
- var x = 'rain-man';
- alert( x ); //弹出 'rain-man'
- }
- rain();
- </script>
是由于在函数rain内局部变量x在整个函数体内都有定义( var x= 'rain-man',进行了声明),所以在整个rain函数体内隐藏了同名的全局变量x。这里之所以会弹出'undefined'是因为,第一个执行alert(x)时,局部变量x仍未被初始化。
所以上面的rain函数等同于下面的函数:
- function rain(){
- var x;
- alert( x );
- x = 'rain-man';
- alert( x );
- }
in , hasOwnProperty()
js 逻辑运算
1,把 a && b 运算 当成 if(a){ b },返回值为执行到的语句。
如:undefined && 1 // undefined
NaN && ""//NaN
[] && ""
0 && "" // 0
"" && 2//
null && 2//
总结 undefined NaN 0 “” null 在if()里都为 false
[] && ""
[] && "" // ""
true && "" // ""
{} && 1 // 报错 , 应该是这样 ({})&& 1
总结[] {}在if()里为true
2,把 a || b 当成 if(a) { } else {b}看,所以,返回值优先考虑 a ,a == true 返回 a, a == false 返回 b
3, ! ==
然而null却不是对象,所以没有constructor这个属性
function clone1(obj1){ function F() {} ; F.prototype = obj1 ; var f = new F() ; for(var key in obj1) { if(typeof obj1[key] =="object") { f[key] = clone1(obj1[key]) } }return f ;}http://bbs.9ria.com/thread-188370-1-1.html
类型转换
Number(null) 0
Number(new Object()) NaN
var s1 = String(null); //"null"
var oNull = null;
var s2 = oNull.toString(); //won’t work, causes an error
3. 利用js变量弱类型转换
举个小例子,一看,就会明白了。
<script>
var str= '012.345 ';
var x = str-0;
x = x*1;
</script>
上例利用了js的弱类型的特点,只进行了算术运算,实现了字符串到数字的类型转换,不过这个方法还是不推荐的
dom操作,节点个数问题
[] == false
- JS学习笔记
- js学习笔记
- js宝典学习笔记
- js学习笔记(一)
- js宝典学习笔记
- Propoty.js学习笔记
- Prototype.js 学习笔记
- JS学习笔记1
- JS学习笔记2
- prototype.js学习笔记
- JS学习笔记
- JS学习笔记1
- prototype.js学习笔记
- js学习笔记
- JS学习笔记一
- JS学习笔记
- js学习笔记
- js学习笔记
- 犹豫不决时的78zb
- 关于cucumber中webrat 模拟浏览器事件操作
- Emacs用dired查找目录树中的所有文件
- ffmpeg的php扩展在php5.4下的安装
- 关于killer网卡在linux 2.6.11版本以上的驱动安装
- js 学习笔记
- 2013 Multi-University Training Contest 4
- 为啥REST如此重要?
- Problem 4:Largest palindrome product
- 由Struct 嵌套定义引出的问题
- 解读struts标签
- 内部类
- LDR指令
- VS2010下 throw语句无响应的奇怪现象