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 Window

5,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;        }        }


易错:函数中声明的变量在整个函数中都有定义。

首先观察这段代码:

view plaincopy to clipboardprint?
  1. <script type="text/javascript">  
  2.     function rain(){  
  3.         var x = 1;  
  4.         function man(){  
  5.             x = 100;  
  6.         }  
  7.         man();        //调用man  
  8.         alert( x );    //这里会弹出 100  
  9.     }  
  10.     rain();    //调用rain  
  11. </script>  

上面得代码说明了,变量x在整个rain函数体内都可以使用,并可以重新赋值。由于这条规则,会产生“匪夷所思”的结果,观察下面的代码。

view plaincopy to clipboardprint?
  1. <script type="text/javascript">  
  2.     var x = 1;  
  3.     function rain(){  
  4.         alert( x );        //弹出 'undefined',而不是1  
  5.         var x = 'rain-man';  
  6.         alert( x );        //弹出 'rain-man'  
  7.     }  
  8.     rain();  
  9. </script>  

是由于在函数rain内局部变量x在整个函数体内都有定义( var x= 'rain-man',进行了声明),所以在整个rain函数体内隐藏了同名的全局变量x。这里之所以会弹出'undefined'是因为,第一个执行alert(x)时,局部变量x仍未被初始化。

所以上面的rain函数等同于下面的函数:

view plaincopy to clipboardprint?
  1. function rain(){  
  2.     var x;  
  3.     alert( x );  
  4.     x = 'rain-man';  
  5.     alert( x );  
  6. }  


in , hasOwnProperty()



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, ! == 


“” == false // true  
!""                // true 这个很特殊,“” 为 false看待了;【】,{} 都为 true 看待(不意味着 {} == true)

[] ==  false //true   【】 为false 不意味着 !【】 为 true
![]                //false


null这个值,既不是引用类型,也不是基本数据类型,但是 typoef null == "object"这个是成立的。
然而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(undefined) NaN
Number(null) 0
Number(new Object()) NaN

最后一种强制类型转换方法String()是最简单的,示例如下:

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

原创粉丝点击