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

JavaScript: The Definitive Guide 权威指南,读书笔记(一)

2013-05-24 23:34 435 查看
// ======================================================================

// 第二章 词法结构

// ======================================================================

// * JavaScript 程序是用Unicode字符编写的。

// * 区分大小写

// * JS会自动给换行的语句插入;来运行。如:

// var article_content = "我们都是神枪手

// 这样可以显示吗?";

// 显然这样是不行的,js会这样来解析

// var article_content = "我们都是神枪手;

// 这样可以显示吗?";

// 这样就是抛出 "Uncaught SyntaxError: Unexpected token ILLEGAL "

// 这么个错误。意思是 不合法的记号(token)。字符串部分出的问题,没有加引号。

// 所以这种时候就要如下一样换行:

//

// var article_content = "我们都是神枪手"

// + "这样可以显示吗?";

// 这是特殊情况,通常如果语句完整,是可以省略的,因为js会自动补上分号解析。

// 原则:都加分号

// * 标识符(identifier):用来命名变量和函数,就是个名字。

// --字母,下划线,美元符开头--

// 字符串,数字这些都是直接量,是token,变量名和函数名也是token,但是也叫标识符

// 在错误提示中可以看出来。

// ======================================================================

// 第三章 数据类型和值

// ======================================================================

// *基本数据类型:number, string, boolean

// 1/1.50, '高'/"圆圆", true/false

// 特殊:null, undefined 既是数据类型也是值

var title = null; var content = undefined;

// note: typeof title == "object", but typeof content == "undefined"

// *复合数据类型:对象 {}/[](也叫数组), 还有一种特殊对象是 函数(可以执行代码的对象,喊他就执行代码)

var me = {

name: 'Ronio',

gender: 'M'

};

var you = ['Caty', 'M'];

var other = new Array('高圆圆', 'F');

function callMe() {

log('你好。');

}

// note: typeof me == "object",

// typeof you == "object" also other

// typeof callMe == "function"

// number:

// var num = 2/2.5/0Xff; 零Xff 16进制 = 15*16+15 = 255

// for fun:

// (25).toString(2-36); // 转换为2-36进制的字符串

//

// 特殊的数值:

// -- Infinity 无穷大的特殊值 2/0 === Infinity, -2/0 == -Infinity

// -- NaN 特殊的非数字值 如:0/0 结果是NaN, but 0/0 !==/!= NaN, NaN 跟谁都不等,包括自己

//

// string:

// 转义:\n 换行符; \r 回车符

//

// e.g.

var s = "let's go to watch 高圆圆的第100部电影-吧?"; // 每个字符都是 2Bates 表示的

log(s.length);

var lastChar = s.charAt(s.length - 1);

var sub = s.substring(1, 4);

var i = s.indexOf('a');

// 函数

//

// 内置了一些函数,如Math.sin()等

// 声明和定义:

//

// function square(x) {

// return x*x;

// }

//

// or

//

// lambda函数 / 匿名函数

// var square = function(x) {

// return x*x;

// }

//

// 对象

var image = {

width: '200px',

height: '400px'

};

var img = new Object();

img.width = '200px';

var pic = {'width': 200, 'height': 400}; // 关联数组

// 数组

var a = new Array(); a[0] = 25; a[10] = 'ni hao'; a[11] = function(){return 'Hi.';};

var b = new Array('cool', 2.5, {a: 20, b: 25});

var c = [1, 2, [3, 4, [5, 6]]];

// null and undefined(使用了未声明的变量、已经声明但为赋值的变量、使用了并不存在的对象属性)

// undefined == null , but undefined !== null

// note: void运算符提供了另一种获取undefined值的方法:

// void 是一个一元运算符, 总是返回undefined

// 如:javascript: void (0);

// 经常看到这样的写法吧,<a href="javascript:void(0);"></a>, 其实void(0);不是一个函数哦,写成 void 0; 也是可以的

// 我之前一直以为是!!

//

// 正则表达式

// 两个斜线之间就OK。/^HTML/ or /\bjavascript\b/i

// Error对象

// 每个Error对象具有一个message属性, throw 和 try那一章去讨论。

//

// 基本数据类型String, Number, Boolean.

// 除了了在eval();中使用有别于 基本类型string,其他和基本类型一样,会自动转换。

// 传给eval()String类型的参数,需要使用.toString()才会和使用string一样。是函数eval()只处理基本类型且不自动转换吗?

//

// ======================================================================

// 第四章 变量

// ======================================================================

// var 声明变量,不能使用delete删除,不使用var,无论在哪直接赋值则为全局变量。

// 只有函数作用域,没有块作用域。

// 原则:变量声明都放开头。

//

// 值和引用,值直接保存在内容中,固定大小;引用,无固定大小,如数组或对象,赋值时复制的是内存地址而不是内容本身。

//

// JavaScript解释器开始运行时,马上创建一个全局对象,使用预定义的值、函数和对象来初始化这个全局对象,

// 定义的全局变量,实际上就是全局对象的属性。

// 局部变量则是调用对象(call object)的属性,还包括参数。

//

// JavaScript的执行环境和变量作用域以后了解。

// 基础:一个执行环境中有全局对象,全局变量(也就是全局对象的属性),调用对象,局部变量。

// 变量名解析过程,是查找和执行环境关联一起的作用域链上的对象是否有这个定义了这个变量。

// 比方:5obj---4obj---3obj---2obj---1obj (这是一个作用域链,*obj就是挂在链条上的对象),

// 当JavaScript开始查询变量X的值时,就开始从1obj-->5obj这样的顺序查找各个对象中是否定义了这个变量,找到就停。

//

// ======================================================================

// 第五章 表达式和运算符

// ======================================================================

// 运算符

// delete, typeof, void instanceof

//

// === 和 ==

// === :

// 1. 两个值类型不同就不同

// 2. 都是数字,有一个是NaN, 则不等

// 3. 都是布尔值,true true才相等

// 4. 都是字符串,同一位置上的字符完全相同则相同。长度或内容不同就不同。

// 注意:Unicode标准允许用多种方法对同样的字符串进行编码,JavaScript逐个比较字符。

// 这种情况可以使用另一种比较方法String.localCompare() ##去看该方法##

// 5. 引用的是相同对象、数组或函数,则相同

// 6. null null相同,undefined undefined相同

// == :

// 1. 类型相同 看值同不同

// 2. 类型不同 类型转换

// 2.1 null == undefined

// 2.2 数字和字符串,则字符串转数字 '2'==2

// 2.3 有个值为 true 转为 1,有个值为 false 转为 0

// 2.4 一个值是对象, 另一个值是数字或字符串,则对象尝试.valueOf(), 然后再尝试.toString()。

// 特殊:Date对象先尝试.toString(), 在.valueOf() --> 输出 timespan 类似 1369232357893

//

// in

// 'attribute' in obj

// '2' in array # 2 是数组下标

//

// instanceof

// obj instanceof classname; # 这里的classname是js对象的.contructor.name, 如果classname为对象,则返回false

//

// && # funny

// 表达式1 && 表达式2 --> 表达式1 可转为false 返回表达式1的值,为true,返回表达式2的值。

// 表达式1 || 表达式2 --> 表达式1 可转为true 返回表达式1的值,为false,返回表达式2的值。

// !

// 一点: 对于任何值应用两次该运算符 !!x 都可以将它转换成一个布尔值。

//

// ======================================================================

// 第六章 语句

// ======================================================================

// throw new Error('some error');

// try/catch/finally

try{

log('语法错误之前发生了什么');

throw new SyntaxError('语法错误');

log('错误之后');

}catch (e){

log(e.constructor.name + e.message);

}finally{

log('我执行了。');

}

// 空语句,最好写注释: for(var i=0; i<10; arr[i++] = 0) /*空语句*/;

//

// ======================================================================

// 第七章 函数

// ======================================================================

//

// 1. function square(x) {

// return x*x;

// }

// 2. var square = function(x){return x*x;}

// 3. var square = new Function("x", "return x*x;");

var square = new Function("x", "log('嘿嘿平方'); return x*x;");

// 函数可以作为数据使用

var operators = {

add : function(x, y){return x+y;},

subtract : function(x, y){return x-y;},

multiply : function(x, y){return x*y;},

divide : function(x, y){return x/y;},

pow : Math.pow

};

function operate(op_name, operand1, operand2) {

if(operators[op_name] == null) {

return 'unknown operator';

}else {

return operators[op_name](operand1, operand2);

}

}

var j = operate('pow', 5, 9); // 5+9=14

// Arguments对象 arguments

// arguments.length 实际参数有几个

// arguments.callee 引用当前正在执行的函数对象

//

(function(x) {

if(x <= 1) return 1;

multiply = x * arguments.callee(x-1);

log("形参个数:"+arguments.callee.length + " VS 实参个数:" + arguments.length); // Function对象的length属性

log(multiply);

return multiply;

})(4, 5);

// 属性prototype, 在new Date 时起作用,具体第八章。

//

// call() 和 apply()

var name = '小高';

function fn() {

log('你好,' + this.name);

}

var obj = {

name: '八戒',

fn : function(){

log('吃饭了' + this.name);

}

};

fn(); // window.fn(), this 为 window, window.name 为 小高

obj.fn(); // 吃放了,八戒。obj内部的事

fn.call(obj); // 比方: fn 是大黄蜂,平常是一辆车,call 来变形金刚,他就是变形金刚的一部分,这是说this,就是指变形金刚,而不是天地了。

// ======================================================================

// 第八章 对象

// ======================================================================

//

// 构造函数:

// 1. 由 new 运算符调用。(很好理解)

// 2. 传递给它的是一个对新创建的空对象的引用,将该引用作为关键字this的值,并

// 对新创建的对象进行适当初始化。构造函数有返回值,则this值所引用的对象就被丢弃了。

function R_area(){}

function R_perimeter(){}

function R_enlarge(){}

function Rectangle(w, h)

{

this.width = w;

this.height = h;

this.area = R_area;

this.perimeter = R_perimeter;

this.enlarge = R_enlarge;

}

var r = new Rectangle(5, 5);

var r1 = new Rectangle(10, 10);

// r, r1 每新建一个对象,就会给对象的每个属性分配内存。如果给 Rectangle类添加X个方法,内存就增加N*X倍。

// 解决办法:原型对象和继承。

//

// ## 这部分比较抽象需要理清楚。##

//

// 函数都有一个prototype属性, prototype属性引用的是该函数的一个对象,也称它为原型对象。

// 对象都有一个constructor属性

//

// 函数本身又是一个对象,我叫这种对象叫函数式对象,所以也有constructor属性,值为 function Function(){ ... },

// (Function这个对象也有constructor属性,就是它本身,

// Function 这个函数的prototype 在 chrome中显示 function Empty(){}, 在IE10中显示 function(){ [native code] })

// 就这样无穷尽也。这里我不是很明白,姑且当作一个称为 “终极函数实例”有能解释下的朋友,可以回复我。

//

// 但是对象本身就不一定是函数了,所以对象不一定有prototype属性了。

//

// 范例说明继承问题:

//

function Fu(){} //这是一个函数,我们要把它当作类,要实例化它。 那么它就是一个构造函数。

function Zi(){} //这是子类的构造函数

Fu.prototype.sayHi = function(){log('Hi, ' + this.constructor.name);}; // 给prototype属性引用的原型对象添加了sayHi方法。

// 所以,实例化一个Fu的对象

var f = new Fu(); // 这时发生了什么?调用叫做Fu的构造函数来构造这个对象。

// 现在 f 是一个对象,不是函数式对象,有constructor属性,但是没有prototype属性。

f.sayHi(); // Hi, Fu

// 继承

Zi.prototype = f; // 试试Fu.prototype。 这样js自己给Zi的prototype引用就丢失了。也可以直接 new Fu();

Zi.prototype.sayHello = function(){log('Hello, ' + this.constructor.name);};

var z = new Zi();

z.sayHi(); // Hi, Fu

z.sayHello(); // Hello, Fu // 可以看出,其实是给 new Fu() 这个对象添加了属性。

Zi.prototype.constructor = Zi; // 其实是设置了 (new Fu())这个实例的constructor

// 如果没有这句,z的constructor属性就丢失了,就会使用父类对象的constructor,

// 对于 instanceof 运算符没有影响

// z instanceof Zi 返回 true

//

// 查找一个对象的属性,就像作用域链一样,一级一级往高处查询。

//

//

// 一句话:

// js的面向对象,就是 同类实例 共享 (某个一个对象)里的属性和方法,

// 如果没有显示指定这个对象,js就自动给你个对象,叫做 原型对象,new 我类者,我是你们的原型。

// 如果显示指定这个对象,那么就是共享 这个对象 已有的属性和方法,js不给你分配了。就是继承。

// 感觉就是一切围绕对象、属性、方法,引用 展开去。

//

//

// JavaScript中所有对象都是继承自 Object()

// 所以所有对象共享Object对象的属性和方法,如下:

// 1. constructor

// 2. hasOwnProperty() 自己本身的属性才是true

z.hasOwnProperty('sayHello'); // false

f.hasOwnProperty('sayHi'); // false

// 一切 原型对象的属性都是false

z.Hi = 'nihao';

z.hasOwnProperty('Hi'); // true

// 3. isPrototypeOf()

Zi.prototype.isPrototypeOf(z); // true Zi.prototype是z的原型对象吗?

f.isPrototypeOf(z); // true

// 4. propertyIsEnumerable()

// 对象直接定义的属性才可以循环枚举出来, 意思同 hasOwnProperty()

//

// 5. toLocaleString() // locale 意思是场所,现场。就是自己根据情况自定义一个字符串返回

// 6. toString() // 返回字符串,代表调用对象的类型或者值

// 7. valueOf() // 和toString比较像,调用回来的可以不是字符串值

//

// ======================================================================

// 第九章 数组

// ======================================================================

//

// 一些方法:

var arr = Array(3); // new Array(4,2,4), [2, 3, 's', obj]

arr.length == 3;

arr.length = 2; // 根据数字大小,截断或者增加 undefined元素

arr[0] = 33;

arr[1] = 4;

// arr[] = 1111; // 这个是不允许的,PHP中就这么弄。

arr[2] = 1111;

arr[3] = 222;

//log(arr.toString()); // 调用toString()属性, "33,4,1111,222"

arr.join('!'); // 33!4!1111!222

arr.reverse(); // 倒过来,返回,原数组上操作的

//log(arr); // 已经倒了。

arr.sort(); // 默认按字母排序,原数组上操作的

//log(arr);

arr.sort(function(a, b){

return a-b; // a-b升序, b-a降序

});

//log(arr);

var arr2 = [4,5,null];

//log( arr.concat(null, arr2) ); // 创建并返回合并后的新数组,不去重。null, undefined都可以。

// slice(开始, 结束); 返回片段

//

// splice(a, b, c...); 插入或删除数组的元素,在元素组上操作。返回删除的数组,b=0,返回[];

//

// push(a), pop() // 数组尾部操作, push 返回新数组长度;pop返回删除的元素

//

// unshift(), shift() // 数组头部操作,unshift返回新数组长度;shift 返回删除的元素

//

// 这四个方法可以用来模拟堆栈和队列

// 栈 push pop 后进先出

// 队列 unshift pop 先进先出

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