Professional javascript For Web Developers 第2版读书笔记(更新中)

1.为了兼容XHtml,对于inline javascript,把代码包裹在//<!CDATA[与//]]>之间。

 

2.使用外部javascript引用的好处:良好的可维护性(js文件可放在同一个目录中) 、缓存(当2个文件引用同一个外部JS时,js文件只下载一次)、避免了XHTML兼容性的问题。

 

3.一般在<body>标签底部引入javascript,目的是为了减少当javascript过大,浏览器编译js而导致页面空白的时间 (整个DOM是按顺序执行,而页面的render是等浏览器接收到<body>标签才开始,若js很大又放在body前面,则会导致页面等待,放在后面则可以等页面载入成功再下载js,对用户来说体验更好)

 

4. javascript有5种类型:undefined,null,bool,number,string。object作为一种复合类型(键值对)存在。

typeof undefined 返回 undefined.

typeof null或者obejct 返回object.

typeof string 返回 string

typeof number 返回 number

typeof bool 返回 bool 

typeof function 返回 function (function在ECMAScript也被认为是object,但是它有一些特殊属性,因此只能用typeof才能区分其他object和function)

typeof RegExp返回function(说明RegExp是function)

5. 声明过的变量,如果未赋初值,则默认会设置为undefined,如果用typeof运算符操作为未声明过的变量也会返回undefined。

 

6.undefined实际上是从null衍生而来,因此 undefined == null 返回 true,但不能认为undefined就是null,null可以理解一个空指针,即变量有值但是为null。 null和undefined没有toString()方法,用String()变换则返回“null"和”undefined“

 

7.javascript对大小写敏感,因此true和false才是bool类型,其他的任意大小写组合都不认为是bool类型

 

8.NaN即Not a number,NaN与参与任何的运算数字都返回NaN,而且NaN==NaN返回false

 

9.恒等运算符 “===”和非恒等运算符 ”==“ 的区别在于恒等不会进行类型转换,而非恒等符会进行转换(cast or convertion)

 

10.for...in语句用来遍历object中所有属性,但是是无序的。

 

11.function如未指定返回值,则默认为undefined,function在其代码块内部都会有一个arguments数组来存储传进来的参数,数组顺序和传进来的参数顺序相同,arguments对象是值传递的。

 

12.javascript中5种基础类型是存放在栈,引用类型Object存放在堆。instanceof用来判断实例属于什么类型,如果是基础类型始终返回false,instanceof Object始终返回true, "sd" instanceof String 返回true

 

13.作用域(scope chain)在js中和其他语言不同,js中不是以代码块{}来区分作用域,而是有个scope chain。最外层的scope通常是global范围的即window,最内层一般属于function内定义的局部变量。

var color = “blue”;
                   
function changeColor(){
    
var anotherColor = “red”;
                   
    
function swapColors(){
        
var tempColor = anotherColor;
        anotherColor 
= color;
        color 
= tempColor;
        
        
//color, anotherColor, and tempColor are all accessible here
    }
                   
    
//color and anotherColor are accessible here, but not tempColor   
    swapColors();
}
                   
//only color is accessible here
changeColor(); 

scope chain为:

window

  color
  anotherColor
    swapColors()
    tempColor
      changeColor()

 

 访问性是有内到外。

 然而no-block level scopes

if (true) {
    
var color = “blue”;
}
                   
alert(color);    
//”blue” 


for (var i=0; i  <  10; i++){
    doSomething(i);
}
                   
alert(i);    
//10 


 14.加了var关键字的变量为局部变量,没家var会默认添加到当前的全局变量中,即window对象中。但是强烈建议不要省略var,在初始化变量之前要声明它

 

 15.function内部包含2个特殊的对象arguments和this,arguments.callee指向的是当前拥有这个arguments的函数指针,arguments属于哪个函数,arguments.callee就是指向哪个函数。this总是当前函数执行时所属的作用域

window.color = “red”;
var o = { color: “blue” };
                   
function sayColor(){
    alert(
this.color);
}
                   
sayColor();     
//”red”
                   
o.sayColor 
= sayColor;
o.sayColor();   
//”blue” 


16.function也属于对象,因此它有2个基本的属性length和prototype。length表示这个function所具有的显示命名的参数个数。prototype是设置类型的方法和属性,而不是属于某个具体实例,类似与c#的静态方法,后面详细介绍


17.apply和call方法基本实现相同的功能。apply方法接受2个参数,一个是运行方法所属的作用域,一个是有参数组成的数组。call方法第一个参数是运行方法所属的作用域,剩下的的参数是要传递的进来的

 

function sum(num1, num2){
    
return num1 + num2;
}
                   
function callSum1(num1, num2){
    
return sum.apply(this, arguments);    //passing in arguments object
}
                   
function callSum2(num1, num2){
    
return sum.apply(this, [num1, num2]); //passing in array
}
                   
alert(callSum1(
10,10));   //20
alert(callSum2(10,10));   //20 


 

function sum(num1, num2){
    
return num1 + num2;
}
                   
function callSum(num1, num2){
    
return sum.call(this, num1, num2);
}
                   
alert(callSum(
10,10));   //20 


 18.Constructor是javascript中的构造函数,它跟一般的函数的主要区别在于:

  1.没有明确的构造对象。

  2.属性和方法函数直接指派到this指针上。

  3.没有return语句返回值

  如:

    

function Person(name, age, job){
    
this.name = name;
    
this.age = age;
    
this.job = job;
    
this.sayName = function(){
        alert(
this.name);
    };    
}
                   
var person1 = new Person(“Nicholas”, 29, “Software Engineer”);
var person2 = new Person(“Greg”, 27, “Doctor”); 

每个具体的实例都有constructor属性,它指向实例所属的类型,

alert(person1.constructor == Person);  //true
alert(person2.constructor == Person);  //true 


自定义构造函数构造的类型还可以通过instanceof运算符来判定实例的类型。

 

alert(person1 instanceof Object);  //true
alert(person1 instanceof Person);  //true
alert(person2 instanceof Object);  //true
alert(person2 instanceof Person);  //true 


 要注意的是:构造一个实例要通过new关键字,这也是constructor和一般function调用方式的不同。另外,这种构造函数的方式有个缺陷就是每个实例都会构造方法,即上例的person1的sayName和person2的sayName是不一样的,通过

alert(person1.sayName == person2.sayName);  //false 可知

 

最好的实现构造函数的方式是prototype(原型模式)

function Person(){
}
                   
Person.prototype.name 
= “Nicholas”;
Person.prototype.age 
= 29;
Person.prototype.job 
= “Software Engineer”;
Person.prototype.sayName 
= function(){
    alert(
this.name);
};
                   
var person1 = new Person();
person1.sayName();   
//”Nicholas”
                   
var person2 = new Person();
person2.sayName();   
//”Nicholas”
                   
alert(person1.sayName 
== person2.sayName);  //true  

 


 prototype的工作原理如下:


 所有的prototypes默认都会自动产生一个constructor属性指向类型本身,如  Person.prototype.constructor指向Person,其他的属性也会被添加到prototype上。每当调用constructor生成一个实例的时候,实例内部会产生一个_proto_属性指向Prototype。虽然实例内部没有定义方法,但是可以调用sayName方法(实际上就是一种继承关系 ),需要注意的是_proto_是没办法通过实例访问的,但是为了验证这种关系存在,isPrototypeOf方法可以检验

alert(Person.prototype.isPrototypeOf(person1));  //true
alert(Person.prototype.isPrototypeOf(person2));  //true  


一旦实例覆盖了prototype的定义的属性值,子类便丧失了访问父类相同属性值的能力,除非用delete关键字

function Person(){
}
                   
Person.prototype.name 
= “Nicholas”;
Person.prototype.age 
= 29;
Person.prototype.job 
= “Software Engineer”;
Person.prototype.sayName 
= function(){
    alert(
this.name);
};
                   
var person1 = new Person();
var person2 = new Person();
                   
person1.name 
= “Greg”;
alert(person1.name);   
//”Greg” - from instance
alert(person2.name);   //”Nicholas” - from prototype
                   
delete person1.name;
alert(person1.name);   
//”Nicholas” - from the prototype  


 hasOwnProperty()方法用来判定属性是属于prototype还是实例本身

function Person(){
}
                   
Person.prototype.name 
= “Nicholas”;
Person.prototype.age 
= 29;
Person.prototype.job 
= “Software Engineer”;
Person.prototype.sayName 
= function(){
    alert(
this.name);
};
                   
var person1 = new Person();
var person2 = new Person();
                   
alert(person1.hasOwnProperty(“name”));  
//false
                   
person1.name 
= “Greg”;
alert(person1.name);   
//”Greg” - from instance
alert(person1.hasOwnProperty(“name”));  //true
                   

下面的图说明了关系是如何

 

 

 判断某个属性是属于实例还是原型的方法可以用

function hasPrototypeProperty(object, name)
{
    
return !object.hasOwnProperty(name)  &  &  (name in object);


 19.默认情况下类型的prototype.constructor会指向类型本身,但如果出现下列情况

function Person(){
}
                   
Person.prototype 
= {
    name : 
"Nicholas",
    age : 
29,
    job : 
"Software Engineer",
    sayName : 
function () {
        alert(
this.name);
    }
}; 

var person = new Person();
alert(person instanceof Object);      //true
alert(person instanceof Person);      //true
alert(person.constructor == Person);  //false
alert(person.constructor == Object);  //true
 

则Person.prototype.constructor会指向一个新的Object对象,而不是原来的Person对象,尽管instanceof仍然返回true,如果为了让constructor指向Person则需要改成

function Person(){
}
                   
Person.prototype 
= {
    constructor: Person,
    name : “Nicholas”,
    age : 
29,
    job : “Software Engineer”,
    sayName : 
function () {
        alert(
this.name);
    }
}; 


 20.prototype上动态修改或者添加方法属性是可以让实例获取到的,因为实例有指向原型(_proto_)的指针。

如:

var person = new Person();
                   
Person.prototype.sayHi 
= function(){
    alert(“hi”);
};
                   
person.sayHi();   
//”hi” - works! 

 

但如果修改的是prototype,则修改的是prototype的指针

如:

function Person(){
}
                   
var person = new Person();
        
Person.prototype 
= {
    constructor: Person,
    name : “Nicholas”,
    age : 
29,
    job : “Software Engineer”,
    sayName : 
function () {
        alert(
this.name);
    }
};
                   
person.sayName();   
//error 

用如下的图来解释:

 

 

 

posted on 2010-07-20 00:08  MoonWalker  阅读(349)  评论(2编辑  收藏  举报

导航