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

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

2010-07-20 00:08 826 查看
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 用如下的图来解释:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: