第一章、引言

1.5 面向对象的程序设计常用概念

对象(名词):是指“事物”在程序设计语言中的表现形式。

这里的事物可以是任何东西,我们可以看到它们具有某些明确特征,能执行某些动作。

这些对象特征就叫做属性(形容词),动作称之为方法(动词)。

类:实际上就是对象的设计蓝图或制作配方。类更多的是一种模板,而对象就是在这些模版的基础上被创建出来的。

封装:主要阐述对象中包含的内容。通常包括:

  • 相关数据(用于存储属性)
  • 基于这些数据所能做的事(所能调用的方法)

聚合:将几个现有对象合并成一个新对象的过程

继承:实现代码重用

多态:不同对象通过相同的方法调用来实现各自行为的能力

第二章、基本数据类型、数组、循环及条件表达式

2.3基本数据类型

2.3.2 指数表示法

2e+3表示在数字2后面加3个0,即2000

typeof Infinity  // number
typeof NaN // number
typeof null // object null值表示一个空指针对象
2.3.4 惰性求值

Javascript引擎在一个逻辑表达式中遇到一个非布尔类型操作数,

那么该操作数的值就会成为该表达式返回的结果。

true || "something"  //true
true && "something" //"something"

2.9 练习题

var s = "1s";  //隐式转换Number()用于任何数据类型
s++ //NaN
10 % "0" //NaN 如果被除数是有限大的数值而除数是零,则结果是NaN
//乘法口诀程序代码
for(var i=1;i<10;i++){
for(var j=1;j<=i;j++){
document.write(j+"*"+i+"="+i*j+" ");
}
document.write("<br>");
}

第三章、函数

3.1 函数

3.1.2 函数参数

函数内部都有一个内建的arguments数组,能返回函数所接收的所有参数

function sumOnSteroids(){
var i,res = 0;
for(i = 0; i < arguments.length; i++){
res += arguments[i];
}
return res;
}
sumOnSteroids(1,2,3,4,5,6); //21

3.3 函数的作用域

var a = 123;
function f(){
alert(a); //undefined 这是因为函数域优先于全局域
var a = 1;
alert(a); //1
}
f();
3.4.2 回调函数

当我们将函数B传递给函数A,并由A来执行B时,B就成了一个回调函数

function A(a,b,c,callback){
var i=0,ar = [];
for(i=0;i<3;i++){
ar[i] = callback(arguments[i]*2);
}
return ar;
}
function B(a){ //回调函数
return a+1;
}
A(a,b,c,B)
3.4.4 自调函数
(function(name){
alert('Hello '+name+' !');
})('Jesse') //Hello Jesse !
//第二对括号起到的是立即调用的作用,同时也是向函数传递参数的地方

使用自调函数的好处是不会产生任何全局变量,缺点是无法重复执行,这使得匿名自调函数最合适于执行一些一次性的或者初始化的任务

3.4.5 私有函数
function a(param){
function b(theinput){ //私有函数
return theinput * 2
};
return 'The result is '+b(param)
}

使用私有函数的好处:

  • 有助于全局命名空间的纯净性(命名冲突的机会很小)
  • 私有性--不被外部其他用用程序所用
3.4.7 能重写自己的函数

这对于要执行某些一次性初始化工作的函数非常有用

function a(){
alert('A'); //第一次调用该函数时该语句会被执行
a = function(){ //第一次调用时a被赋予新函数
alert('B'); //第二次调用该函数时该语句会被执行
};
}
var a = function(){
function someSetup(){
var setup = 'done'
}
function actualWork(){
alert('work')
}
someSetup();
return actualWork;
}();

3.5 闭包

3.5.1 作用域链

在函数内定义的变量在函数外是不可见的,

但是如果该变量是在某个代码块中定义的(if或for语句中),它在代码块外是可见的。

3.5.2 词法作用域

在javascript中每个函数都有一个属于自己的词法作用域,也就是说每个函数

在被定义时(而非执行时)都会创建一个属于自己的环境(即作用域)

function f1(){var a = 1;f2();}
function f2(){return a;} //f2()被定义时a是不可见的,只能访问自身作用域和全局作用域
f1(); //a is not defined
3.5.3 利用闭包突破作用域链
3.5.3.1 闭包#1
function f(){
var b = "m";
return function(){ //有着私有作用域,可以访问f()的作用域和全局作用域
return b;
}
}
var n = f();
n(); //m

f()是全局函数,我们可以将它的返回值赋值给另一个全局变量,

从而生成一个可以访问f()私有空间的新全局函数

3.5.3.3 相关定义与闭包#3

如果一个函数在其父函数返回之后想留住对父级作用域的链接,就必须要为此建立一个闭包

3.5.3.4 循环中的闭包
function f(){
var a = [];
for(var i = 0; i < 3; i++){
a[i] = function(){
return i;
}
}
return a;
}
var s = f();
s[0](); //3
s[1](); //3
s[2](); //3

我们在这里创建了3个闭包,它们都指向一个共同的局部变量i,

但是闭包不会记录它们的值,他们所拥有的只是一个i的引用,

因此只能返回i的当前值(循环结束时i=3).

function f(){
var a = [];
for(var i = 0; i < 3; i++){
a[i] = (function(x){
return function(){
return x;
}
})(i);
}
return a;
}
var s = f();
s[0](); //0
s[1](); //1
s[2](); //2

3.7 练习题

1.十六进制值转为颜色函数getRGB()

function getRGB(hex){
var rgb=[0,0,0];
if(/#(..)(..)(..)/g.test(hex)){
rgb=[parseInt(RegExp.$1,16),parseInt(RegExp.$2,16),parseInt(RegExp.$3,16)];
};
return "rgb("+rgb.join(",")+")";
}
getRGB('#00ff00'); //"rgb(0,255,0)"

第四章、对象

4.1 从数组到对象

用[]定义数组的方法我们称之为数组文本标识法

用{}定义对象的方法我们称之为对象文本标识法

4.1.2 哈希表、关联型数组

在javascript中我们用数组表示索引型数组,用对象表示关联型数组

4.1.3 访问对象属性

一般通过以下两种方式访问对象的属性:

  • 中括号表示法:hero['name']
  • 点号表示法:hero.name
4.1.7 构造器函数
function Hero(name){  //构造器函数首字母大写
this.name = name;
this.occupation = 'ninja'
}
var hero = new Hero('jesse'); //使用new操作符创建新对象
hero.name; //ninja

使用构造器函数的好处是能利用同一个构造器函数通过传参从而创建出不同的对象。

4.1.8 全局对象

事实上程序所在的宿主环境一般都会为其提供一个全局对象,

而所谓的全局变量其实只不过是该对象的属性

4.1.9 构造器属性

构造器属性实际上是一个指向用于创建该对象的构造器函数的引用

hero.contructor //Hero

通过instanceof操作符,我们可以测试一个对象是不是由某个指定的构造器函数所创建的

hero instanceof Hero; //true

4.1.12 传递对象

引用类型,因为其值大小不固定,因此栈内存中存放的只是该对象的访问地址,(即该对象的引用)

堆内存为这个值分配空间。因此我们在引用上所做的任何改动,都会影响到他所引用的源对象。

4.2 内建对象

4.2.1 Object

所有对象都继承自Object对象,因此都具有toLocaleString()、toString()和valueOf()方法。

var o = new Object();
var o = {};
alert(o); //[object,Object]

由于alert()要接收字符串参数,所以它会在后台调用toString()方法

Object构造器的成员:

用Object()构造器所建对象的成员:





4.2.2 Array
var a = new Array();
var a = [];
typeof a; //'object' 数组也是对象

值得关注的数组的属性与方法

  • length属性:定义数组时会自动生成length属性,而一般对象中没有
  • sort()、join()、slice()、splice()

Array对象的成员:







4.2.3 Function

函数实际上也是一种对象,函数对象的内建构造器是Function()

定义函数的三种方式:

  • function sum(a,b){return a + b;}; //函数声明
  • var sum = function(a,b){return a + b;}; //函数表达式
  • var sum = new Function('a','b','return a + b;'); //Function构造器 避免使用
4.2.3.1 Function对象的属性:
  • prototype属性详见第五章
  • length:用于记录该函数所拥有的参数数量
  • caller:返回一个调用该函数对象的外层函数引用
function A(){return A.caller;}
function B(){return A();}
B(); //function B(){return A();}
4.2.3.2 Function对象的方法

Function对象继承自Object对象,默认拥有Object对象的所有方法

call()、apply()方法都能让对象去借用其他对象中的方法为己所用,这也是一种代码重用的方式。

  • call()方法:
var someObj = {
name: 'Ninja',
say: function(who){
return 'Hello '+who+', my name is '+ this.name;
}
};
var myObj = {
name:'Jesse'
};
someObj.say.call(myObj, 'Dude');//"Hello Dude, my name is Jesse"
//当say()被调用时其中的this就被自动设置成myObj对象的引用

如果我们调用call方法时需要传递更多的参数,可以在后面依次加入他们

someObj.say.call(myObj,'a','b','c')

如果我们没有将对象传递给call()的首参数,或者传递的是null,则它的调用对象默认为全局对象

  • apply()方法:

    apply()的工作方式与call()基本相同,唯一的不同之处在于第二个参数的传递形式apply()方法的第二个参数是通过一个数组来传递的

someObj.say.apply(myObj,['a','b','c'])

4.2.3.3 重新认识arguments对象
  1. 在函数中通过arguments访问传递给函数的所有参数
  2. arguments对象的callee属性,该属性返回的是当前被调用的函数对象
  3. 通过arguments.callee属性实现匿名函数的递归调用
(function(count){
if(count < 5){
console.log(count);
arguments.callee(++count);
}
})(1) //1,2,3,4

Function对象的成员



4.2.4 Boolean
var b = new Boolean();
typeof b; //'object'
typeof b.valueOf();// 'boolean'
4.2.5 Number

Number对象的toString()方法有一个可选的radix参数(默认10)

var n =new Number(255);
n.toString(16); // 'ff'

Number()构造器的成员



Number对象的成员



4.2.6 String

当我们将一个基本字符串当做对象来使用时,后台会执行相应的String对象创建操作

String()构造器的成员

String对象的成员







4.2.7 Math

Math对象既不能当做一般函数来使用,也不能用new操作符创建对象,只是一个包含一系列方法和属性的内建对象

获取某个max和min之间的值,公式((max-min)*Math.random())+min

Math对象的成员



4.2.8 Date

Date()构造器成员

Date对象的成员









4.2.9 RegExp
var reg = new RegExp('j.*t');
var reg = /j.*t/; //匹配任何以j开头t结尾的字符串,且这俩字符之间包含1个或多个字符
4.2.9.1 RegExp对象的属性
  • global:如果该值为false(默认),相关搜索在找到第一个匹配位置时就会停止,如果为true则会找出所有匹配位置,简写为‘g’
  • ignoreCase:设置是否忽略大小写,默认为false,简写为'i'
  • multiline:设置是否跨行搜索,默认为false,简写为'm'
  • lastIndex:搜索开始的索引位置,默认为0。在对象创建之后可以修改
  • source:用于存储正则表达式匹配模式

var reg = /j.*t/img;

4.2.9.2 RegExp对象的方法
  • test():返回的是一个布尔值(找到匹配内容为true,否则为false)
  • exec():返回的是一个由匹配字符串组成的数组
/j.*t/i.test('Javascript')   //true
/j.*t/i.exec('Javascript')[0] //Javascript
4.2.9.3 以正则表达式为参数的字符串方法
  • match():返回的是一个包含匹配内容的数组
  • search():返回的是第一个匹配内容所在的位置
  • replace():将匹配的文本替换成指定的字符串
  • split():根据指定的正则表达式将目标字符串分割成若干数组元素
var s = new String('HelloJavascriptWorld');
s.match(/j.*a/ig); //['Java']
s.search(/j.*a/i); //5
//当某个匹配对象被找到时,如果我们想让相关的替换字符串中包含匹配的文本,可以使用$&修饰符
s.replace(/[A-Z]/g,'_$&'); //"_Hello_Javascript_World"
//如果正则表达式分了组(即带括号),那么可以用$1代表匹配分组中的第一组,$2代表第二组
s.replace(/[A-Z]/g,'_$1'); //"_Hello_Javascript_World"
var csv = 'one, two,three ,four';
csv.split(/\s*,\s*/) //["one", "two", "three", "four"]
// \s*匹配0个或多个空格
//以上的4个方法可以接受的参数也包括字符串
"test".replace('t','r'); //"rest"

RegExp对象的成员



4.2.10 Error对象
try{
//可能会导致错误的代码
}catch(e){
//在发生错误时处理代码
}finally{ //可选的
//无论如何都会执行的代码
}

4.4 练习题

c = [1,2,[1,2]];
c.sort(); //[1, [1,2], 2]

4、在String()构造器不存在时,自定义MyString()构造器函数并通过以下测试

function MyString(string){
//this.length =
this.toString = function(){
return string.toString();
}
this.valueOf = function(){
return string.valueOf();
}
this.reverse = function(){
return Array.prototype.reverse.apply(string.split('')).join('');
}
}
var s = new MyString('hello');
s.length; //5
s[0]; //'h'
s.toString(); //'hello'
s.valueOf(); //'hello'
s.chatAt(1); //'e'
s.concat(' world!'); //'hello world!'
s.slice(0,-1); //'hell'
s.split('l'); //['he','','o']

6、在Array()不存在时,创建MyArray()构造器并通过以下测试

var a = new MyArray(1,2,3,'test');
a.length;//4
a.toString();//'1,2,3,test'
a[a.length - 1];//'test'
a.push('boo');//5
a.pop();//'1,2,3,test'
a.join(',');//'1,2,3,test'
function MyArray(){
this.length =
}

第五章、原型

5.1 原型属性

5.1.4 利用自身属性重写原型属性

如果在一个对象自身属性中没有找到指定的属性,就可以去原型链中查找相关属性。但是如果遇上对象自身属性与原型链属性同名时,那么对象自身属性的优先级高于原型链属性。

function Gadget(name,color){
this.name = name;
this.color = color;
this.method =function(){
return 1;
}
}
Gadget.prototype.price = 10;
Gadget.prototype.rating = 3;
var newtoy = new Gadget('webcam','back');
for(var prop in newtoy){
console.log(prop + '=' + newtoy[prop]);
}
//name=webcam
//color=back
//method=function (){return 1;}
//price=10
//rating=3

hasOwnProperty()方法用于区分对象自身属性(返回true)与原型属性(返回false)

newtoy.hasOwnProperty('name');   //true
newtoy.hasOwnProperty('price'); //false

propertyIsEnumerable()方法对所有非内建对象属性返回true,表示可通过for-in枚举;

newtoy.propertyIsEnumerable('name'); //true

isPrototypeOf()方法会告诉我们当前对象是否是另一个对象的原型

var monkey = {
hair:true,
feeds:'bananas',
breathes:'air'
};
function Human(name){
this.name = name;
}
Human.prototype = monkey;
var jesse = new Human('Jesse');
monkey.isPrototypeOf(jesse); //true

5.2 扩展内建对象

为Array对象添加inArray()方法,用于查询数组中是否存在某个特定的值

if(!Array.prototype.inArray){  //如果想通过原型为某个对象添加新属性,请务必检查该属性是否已存在
Array.prototype.inArray = function (needle){
for(var i = 0;i < this.length; i++){
if(this[i] == needle){
return true;
}
}
return false;
}
}
var a = ['a','b','c'];
a.inArray('d'); //false

为String对象添加reverse()方法,用于反向输出该字符串

if(!String.prototype.reverse){  //如果想通过原型为某个对象添加新属性,请务必检查该属性是否已存在
String.prototype.reverse = function(){
return Array.prototype.reverse.apply(this.split('')).join('');
}
}
"Jesse".reverse(); //"esseJ"
//首先利用this.split('')将目标字符串转为数组,并作为apply()的第二个参数,第一个参数不传值时默认为全局对象
//再调用数组的reverse()方法生成反向数组
//最后通过join()方法将数组转化为字符串
5.2.2 原型陷阱
  • 当我们对原型对象完全替换时,可能会触发异常
  • prototype.constructor属性不可靠

解决方法:当我们重写某对象的prototype时,必须重置相应的constructor属性

5.4 练习题

var shape = {
type:"triangle",
getType:function(){
return this.type;
}
}
function Triangle(a,b,c){
this.a = a;
this.b = b;
this.c = c;
}
Triangle.prototype = shape;
//当我们重写某对象的prototype时,必须重置相应的constructor属性
Triangle.prototype.constructor = Triangle;
Triangle.prototype.getPerimeter = function(){
return this.a + this.b + this.c;
}
var t = new Triangle(1,2,3);
for(var prop in t){
if(t.hasOwnProperty(prop)){
console.log(prop + '=' + t[prop]);
}
}
t.constructor; //Trianle(a,b,c)
shape.isPrototypeOf(t); //true
t.getPerimeter(); //6
t.getType(); //"triangle"

第六章、继承

6.1 原型链

6.1.1 原型链示例
function Shape(){
this.name = 'shape';
this.toString = function(){return this.name;};
}
function TwoDShape(){
this.name = '2D shape';
}
function Triangle(side,height){
this.name = 'Triangle';
this.side = side;
this.height = height;
this.getArea = function(){
return this.side*this.height/2;
}
}
TwoDShape.prototype = new Shape();
Triangle.prototype = new TwoDShape();
//我们用构造器Shape()另建了一个新的实体,然后用它去覆盖该对象的原型
//这确保了在继承实现之后,我们对Shape()所进行的任何修改、重写、删除都不会对TwoShape()产生影响
TwoDShape.prototype.constructor = TwoDShape;
Triangle.prototype.constructor = Triangle;
var my = new Triangle(5,10);
my.getArea();//25
my.toString(); // Triangle
6.1.2 将共享属性迁移到原型中
function Shape(){};
Shape.prototype.name = 'shape';
Shape.prototype.toString = function(){return this.name;};
function TwoDShape(){};
TwoDShape.prototype = new Shape();
TwoDShape.prototype.constructor = TwoDShape;
//我们需要在对原型对象进行扩展之前,先完成相关继承关系的构建
TwoDShape.prototype.name = '2D shape';
function Triangle(side,height){
this.side = side;
this.height = height;
}
Triangle.prototype = new TwoDShape();
Triangle.prototype.constructor = Triangle;
Triangle.prototype.name = 'Triangle';
Triangle.prototype.getArea = function(){
return this.side*this.height/2;
}

6.2 只继承于原型

function Shape(){};
Shape.prototype.name = 'shape';
Shape.prototype.toString = function(){return this.name;};
function TwoDShape(){};
//TwoDShape.prototype = new Shape(); new Shape()会将Shape的属性设定为对象自身属性,这样的代码是不可重用的
TwoDShape.prototype = Shape.prototype;
TwoDShape.prototype.constructor = TwoDShape;
TwoDShape.prototype.name = '2D shape';
function Triangle(side,height){
this.side = side;
this.height = height;
}
Triangle.prototype = TwoDShape.prototype;
//这样固然可以提高效率,但是子对象和父对象都指向同一对象,一旦对原型属性进行修改,继承的对象相关属性也随之改变
Triangle.prototype.constructor = Triangle;
Triangle.prototype.name = 'Triangle';
Triangle.prototype.getArea = function(){
return this.side*this.height/2;
}
var s = new Shape();
s.name;//"Triangle"

6.3 uber--子对象访问父对象的方式

在构建继承关系的过程中引入一个uber属性,并令其指向其父级原型对象

6.8 深拷贝

当对象类型的属性拷贝时,实际上拷贝的只是该对象在内存中的位置指针,这一过程就是浅拷贝

//浅拷贝
function extendCopy(p){
var c = {};
for(var i in p){
c[i] = p[i];
}
c.uber = p;
return c;
}
//深拷贝
function deepCopy(p,c){
var c = c || {};
for(var i in p){
if(typeof p[i] === 'object'){
c[i] = (p[i].constructor == Array) ? [] : {};
deepCopy(p[i],c[i]); //在遇到一个对象引用型的属性时,需要再次调用深拷贝
}else{
c[i] = p[i];
}
}
return c;
}
var parent = {
numbers:[1,2,3],
letters:['a','b','c'],
obj:{prop:1},
bool:true
};
var mydeep = deepCopy(parent);
var myshallow = extendCopy(parent);
mydeep.numbers.push(4,5,6); //6
mydeep.numbers; //[1, 2, 3, 4, 5, 6]
parent.numbers; //[1, 2, 3]
myshallow.numbers.push(10); //4
myshallow.numbers; //[1, 2, 3, 10]
parent.numbers; //[1, 2, 3, 10]
mydeep.numbers; //[1, 2, 3, 4, 5, 6]

6.9 object

基于在对象之间直接构建继承关系的理念,可以用object()来接收父对象,并返回一个以该父对象为原型的

新对象。

function object(p){
function F(){};
F.prototype = p;
return new F();
}

6.12 寄生式继承

var twoD = {
name:'2d shape',
dimensions:2
}
function triangle(s,h){
var that = object(twoD);//把twoD对象全属性拷贝进that对象
that.name = 'Triangle';
that.getArea = function(){return this.side * this.height / 2};
that.side = s;
that.height = h;
return that;
}

6.14 本章小结

实现继承的方法大致上分为两类:

  • 基于构造器工作模式
  • 基于对象工作模式





6.15 案例学习:图形绘制

未完成

第七章、浏览器环境

7.3 BOM

7.3.1 Window对象
window.open('新URL','新窗口名','以逗号分割的功能性列表')
window.close();
window.moveTo(x,y);
window.moveBy(x,y);
window.resizeTo(x,y);
window.resizeBy(x,y);
window.alert();
window.prompt(); //点击确认返回相应文本,点击取消返回null
window.confirm();//点击确认返回true,点击取消返回false
window.setTimeout();//指定多长时间后执行代码
window.setInterval();//指定每隔多长时间执行代码
7.3.2 navigation对象

navigation.userAgent是一个用户浏览器识别的长字符串,但不要过分依赖这种用户代理字符串,

浏览器能力检测是更好地选择

  • 这种字符串很难追踪到所有的浏览器以及其各种版本
  • 这种字符串可以被修改
7.3.3 location对象

localtion对象的完整属性:

  • href
  • hash
  • host
  • hostname
  • port
  • protocol
  • search

location对象的方法:

  • reload()重载某页面
  • assign()打开新URL,并在历史记录中生成新纪录
  • replace()与assign()相同,但不会生成新纪录
7.3.4 history对象

history.forward();history.back();

7.3.5 screen对象
screen.width();
screen.availwidth();

7.4 DOM

7.4.2 DOM节点的访问
hasChildNodes()方法用于判断一个节点是否存在子节点
hasAttributes()方法用于检查该元素中书否存在属性
document.documentElement.childNodes.length; //2
//任何节点都可以通过自身的parentNode来访问它的父节点
document.documentElement.parentNode; //<html>
document.getElementsByTagName();
document.getElementsByName();
document.getElementById();
nextSibling/previousSibling;
firstChild/lastChild
7.4.4 新建节点
createElement();
var myp = document.createElement('p');
createTextNode();//新建文本节点
appendChild();
document.body.appendChild(myp);
cloneNode(true)//true深拷贝 false浅拷贝
insertBefore(要插入的节点,参照节点);
replaceChild(要插入的节点,要替换的节点)
removeChild(要移除的节点);

7.5 事件

7.5.3 DOM的事件监听器
addEventListener('事件类型',函数指针[,false]);
removeEventListener('事件类型',函数指针[,false]);
//匿名函数所定义的监听器是不能被移除的

该方法基于某一节点对象来调用,第三个参数决定代码是否采用事件捕捉,可选的,为了适应更多的浏览器,我们一般将其设置为false,即采用事件冒泡。

7.6 XMLHttpRequest对象

//创建xhr对象
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject("Microsoft.XMLHTTP")
}
//设置一个能触发readystatechange事件的事件监听器,及处理响应程序
xhr.onreadystatechange=function(){
if (xhr.readyState==4 && xhr.status==200){
console.log(xhr.responseText);
}
}
//open(请求类型,请求目标URL,是否异步请求)
xhr.open('GET','somefile.txt',true);
//发送请求
xhr.send('')

7.8 练习题

2.3
function include(js){
var script = document.createElement('script');
script.src = js;
document.body.appendChild(script);
}
include('somescript.js');
3.1
var myevent = {
addListener:function(el,type,fn){
if(typeof window.addEventListener === 'function'){
myevent.addListener = function(el,type,fn){
el.addEventListener(type,fn,false);
};
}else if(typeof window.attachEvent === 'function'){ //code for IE
myevent.addListener = function(el,type,fn){
el.attachEvent('on'+type,fn);
};
}else{ // code for older browsers
myevent.addListener = function(el,type,fn){
el['on' + type] = fn;
};
}
myevent.addListener(el,type,fn);
},
removeListener : function(el,type,fn){
if(typeof window.removeEventListener === 'function'){
myevent.removeListener = function(el,type,fn){
el.removeEventEventListener(type,fn,false);
};
}else if(typeof window.detachEvent === 'function'){ //code for IE
myevent.removeListener = function(el,type,fn){
el.detachEvent('on'+type,fn);
};
}else{ // code for older browsers
myevent.removeListener = function(el,type,fn){
el['on' + type] = null;
};
}
myevent.removeListener(el,type,fn);
},
getEvent:function(event){},
getTarget:function(event){},
stopPropagation:function(event){},
preventDefault:function(event){}
}
4.1
var ajax ={
request:function(url,requestType,queryString){
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject("Microsoft.XMLHTTP")
}
xhr.onreadystatechange = function(){
if (xhr.readyState == 4 && xhr.status == 200){
console.log(xhr.responseText);
}
}
xhr.open(requestType,url,true);
xhr.send('');
}
}
ajax.request('some.txt','get');

第八章、编程模式与设计模式

8.1 编程模式

8.1.2 命名空间与初始化分支模式

为了减少命名冲突,最好的办法是将变量和方法定义在不同的命名空间中,这种方法的实质是只定义一个全局变量,

并将其他的方法和属性定义为该变量的属性。

var mySpace = {};
mySpace.event = {
addListener:null,
removeListener:null
……
}
if(typeof window.addEventListener === 'function'){
mySpace.event.addListener = function(el,type,fn){
el.addEventListener(type,fn,false);
};
mySpace.event.removeListener = function(el,type,fn){
el.removeEventListener(type,fn,false);
};
}else if(typeof window.attachEvent === 'function'){ //code for IE
mySpace.event.addListener = function(el,type,fn){
el.attachEvent('on'+type,fn);
};
mySpace.event.removeListener = function(el,type,fn){
el.detachEvent('on'+type,fn);
};
}else{ // code for older browsers
mySpace.event.addListener = function(el,type,fn){
el['on' + type] = fn;
};
mySpace.event.removeListener = function(el,type,fn){
el['on' + type] = null;
};
}
8.1.4 延迟定义模式
var mySpace = {};
mySpace.event = {
addListener:function(el,type,fn){
if(typeof window.addEventListener === 'function'){
mySpace.event.addListener = function(el,type,fn){
el.addEventListener(type,fn,false);
};
}else if(typeof window.attachEvent === 'function'){ //code for IE
mySpace.event.addListener = function(el,type,fn){
el.attachEvent('on'+type,fn);
};
}else{ // code for older browsers
mySpace.event.addListener = function(el,type,fn){
el['on' + type] = fn;
};
}
mySpace.event.addListener(el,type,fn);
}
};
8.1.5 配置对象

该模式适用于有很多参数的函数或方法

用单个对象来替代多个参数有以下几点优势:

  • 不用考虑参数的顺序
  • 可以跳过某些参数的设置
  • 函数的扩展性强
  • 代码可读性好
var myapp = {};
myapp.dom = {};
myapp.dom.Button = function(text,conf){
var type = conf.type || 'submit';
var font = conf.font || 'microsoftyahei';
//……
}
//使用方法如下:
var config = {
font:'Arial,Verdana,microsoftyahei',
color:'#fff'
};
new myapp.dom.Button('lalala',config);
8.1.6 私有属性和方法
8.1.7 特权函数
8.1.8 私有函数的公有化
8.1.9 自执行函数
(function(){
// code in here
})()
//该模式特写适用于某些脚本加载时所执行的一次性初始化工作
8.1.10 链式调用

构造器返回的是新建对象的this指针,我们可以使用这些方法所返回的实例来调用其他方法

document.body.appendChild(
new mySpace.dom.Element('span')
.setText('hello')
.setStyle('color','red')
);
8.1.11 JSON

var obj = JSON.parse(xhr.responseText);

8.2 设计模式

8.2.2 单件模式
8.2.3 工厂模式
8.2.4 装饰器模式
8.2.5 观察者模式

《JavaScript面向对象的编程指南》--读书笔记的更多相关文章

  1. csapp读书笔记-并发编程

    这是基础,理解不能有偏差 如果线程/进程的逻辑控制流在时间上重叠,那么就是并发的.我们可以将并发看成是一种os内核用来运行多个应用程序的实例,但是并发不仅在内核,在应用程序中的角色也很重要. 在应用级 ...

  2. CSAPP 读书笔记 - 2.31练习题

    根据等式(2-14) 假如w = 4 数值范围在-8 ~ 7之间 2^w = 16 x = 5, y = 4的情况下面 x + y = 9 >=2 ^(w-1)  属于第一种情况 sum = x ...

  3. CSAPP读书笔记--第八章 异常控制流

    第八章 异常控制流 2017-11-14 概述 控制转移序列叫做控制流.目前为止,我们学过两种改变控制流的方式: 1)跳转和分支: 2)调用和返回. 但是上面的方法只能控制程序本身,发生以下系统状态的 ...

  4. CSAPP 并发编程读书笔记

    CSAPP 并发编程笔记 并发和并行 并发:Concurrency,只要时间上重叠就算并发,可以是单处理器交替处理 并行:Parallel,属于并发的一种特殊情况(真子集),多核/多 CPU 同时处理 ...

  5. 读书笔记汇总 - SQL必知必会(第4版)

    本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...

  6. 读书笔记--SQL必知必会18--视图

    读书笔记--SQL必知必会18--视图 18.1 视图 视图是虚拟的表,只包含使用时动态检索数据的查询. 也就是说作为视图,它不包含任何列和数据,包含的是一个查询. 18.1.1 为什么使用视图 重用 ...

  7. 《C#本质论》读书笔记(18)多线程处理

    .NET Framework 4.0 看(本质论第3版) .NET Framework 4.5 看(本质论第4版) .NET 4.0为多线程引入了两组新API:TPL(Task Parallel Li ...

  8. C#温故知新:《C#图解教程》读书笔记系列

    一.此书到底何方神圣? 本书是广受赞誉C#图解教程的最新版本.作者在本书中创造了一种全新的可视化叙述方式,以图文并茂的形式.朴实简洁的文字,并辅之以大量表格和代码示例,全面.直观地阐述了C#语言的各种 ...

  9. C#刨根究底:《你必须知道的.NET》读书笔记系列

    一.此书到底何方神圣? <你必须知道的.NET>来自于微软MVP—王涛(网名:AnyTao,博客园大牛之一,其博客地址为:http://anytao.cnblogs.com/)的最新技术心 ...

  10. Web高级征程:《大型网站技术架构》读书笔记系列

    一.此书到底何方神圣? <大型网站技术架构:核心原理与案例分析>通过梳理大型网站技术发展历程,剖析大型网站技术架构模式,深入讲述大型互联网架构设计的核心原理,并通过一组典型网站技术架构设计 ...

随机推荐

  1. asp.net MVC 5 路由 Routing

    ASP.NET MVC ,一个适用于WEB应用程序的经典模型 model-view-controller 模式.相对于web forms一个单一的整块,asp.net mvc是由连接在一起的各种代码层 ...

  2. redis 系列3 数据结构之简单动态字符串 SDS

    一.  SDS概述 Redis 没有直接使用C语言传统的字符串表示,而是自己构建了一种名为简单动态字符串(simple dynamic string, SDS)的抽象类型,并将SDS用作Redis的默 ...

  3. pyinstaller安装配置

    一.工具准备: 1).安装pyinstaller需要以这个包为基础.也就是基础软件包.pyWin32包.下载对应的pyWin32安装包>>地址: https://sourceforge.n ...

  4. 【EF6学习笔记】(九)异步处理和存储过程

    本篇原文:Async and Stored Procedures 为何要采用异步? 一个Web服务器肯定有可用线程的限制,那么在一些访问量特别大的情况下,线程肯定会消耗完:这个时候服务器肯定处理不了请 ...

  5. Consul安装使用

    安装 安装环境: Mac 我参照官网下载,然后解压,然后添加到PATH,并不能用.最终使用brew安装成功. brew install consul 安装成功后,文件位于/usr/local/Cell ...

  6. Spark内存管理机制

    Spark内存管理机制 Spark 作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色.理解 Spark 内存管理的基本原理,有助于更好地开发 Spark 应用程序和进行 ...

  7. LeetCode-63. 不同路径 II

    最近英文版的访问特别慢,转战中文吧 和上一题一样,递归会超时 //63 不同路径2,递归解法 int uniquePaths2(vector<vector<int>>& ...

  8. Python爬虫的N种姿势

    问题的由来   前几天,在微信公众号(Python爬虫及算法)上有个人问了笔者一个问题,如何利用爬虫来实现如下的需求,需要爬取的网页如下(网址为:https://www.wikidata.org/w/ ...

  9. T-SQL基础(五)之增删改

    在前面的文章中对T-SQL的查询做了基本总结,接下来我们看下SQL中的另外一个常用操作——数据的修改. INSERT INSERT 向数据表中插入数据的基本语句,句式: INSERT INTO tab ...

  10. Discuz网警过滤关键词库

    积累近几年discuz关键词过滤 使用方法:1.进入后台/内容/词语过滤批量添加.2.打开CensorWords.txt,复制里面的文本信息到批量添加的输入框内,点击确定即可.如图: 关键词下载:Ke ...