第六章 面向对象的程序设计
数据属性:包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有4个描述其行为的特性
[[Configurable]]:表示能否通过delete删除属性从而重新定义属性
[[Enumerable]]:表示能否通过for-in循环返回属性
[[Writeable]]:表示能否修改属性的值
[[Value]]:包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置
alert(person.name); //"Nicholas"
访问器属性:包包含数据值;它们包含一对getter和setter函数。在读取访问器属性时,会掉用getter函数,这个函数负责返回有效的值。在写入访问器属性是,会掉用setter函数,这个函数负责决定如何处理数据
[[Configurable]]:表示能否通过delete删除属性从而重新定义属性
[[Enumerable]]:表示能否通过for-in循环返回属性
[[Get]]:在读取属性时调用的函数
[[Set]]:在写入属性时掉用的函数
如果只有Get函数则这个属性不能写,如果只有Set函数则这个属性不能读
修改属性默认的特性,使用objet.defineProperty()方法。必须接收三个参数:属性所在的对象、属性名字、和一个描述符对象的属性
例1:修改数据属性
var person = {};
Object.defineProperty(person, "name", {
writable: false;
value: "Nicholas"
});
例2:修改访问器属性
var book = {
_year: 2004,
edition: 1
};
Object.defineProperty(book,"year"), {
get: function()
return this._year;
},
set: function(newValue){
if(newValue > 2004) {
this._year = newVlaue;
this.edition += newValue - 2004;
}
}
});
定义多个属性:
var book = {};
Object.defineProperty(book, {
-year: {
writable:true;
value: 2004
},
edition: {
writable: ture;
value: 1;
}
year: {
get: function() {
return this._year;
}
},
set: function(newValue){
if(newValue > 2004) {
this._year = newVlaue;
this.edition += newValue - 2004;
}
}
});
读取属性的特性:
Objecgt.getOwnPropertyDescriptor()方法
接收两个参数:属性所在的对象、要读取其描述符的属性名称
var book = {};
Object.defineProperty(book, {
-year: {
writable:true;
value: 2004
},
edition: {
writable: ture;
value: 1;
}
year: {
get: function() {
return this._year;
}
},
set: function(newValue){
if(newValue > 2004) {
this._year = newVlaue;
this.edition += newValue - 2004;
}
}
});
var descriptor = Object. getOwnPropertyDescriptor(book,"_year");
alert(descriptor.value);
alert(descriptor.configurable);
工厂模式:
使用简单的函数创建对象,为对象添加属性和方法。然后返回对象。这个模式后来被姑咱函数模式所取代
构造函数模式:
可以创建自定义引用类型,可以像创建内置对象实例一样使用new操作符。不过,构造函数 也有缺点,即它的每个成员都无法得到复用,包括函数。由于函数可以不局限任何对象,因此没有理由不在多个对象间共享函数
原型模式:
使用构造函数的prototype属性指定那些应该共享的属性和方法。。组合使用构造函数模式和原型模式时,使用构造函数定义实例属性,而使用原型定义共享的属性和方法
继承:JavaScript 主要通过原型链实现继承。原型链的构建是通过一个新类型的实例赋给另一个构造函数原型实现的。子类型局能够方法超类型所有的属性和方法,这一点与基于类的继承很相似。原型链的问题是对象实例共享所有继承的属性和方法,因此不能单独使用。解决这个问题的技术是借用构造函数,即在子类型构造函数的内部调用超类型构造函数。这样就可以做到每个实例都有自己的属性,同时还能保证只使用构造函数模式来定义类型。
原型式继承:
可以在不必预先定义构造函数的情况下实现继承,其本质是执行对给定对象的复制
寄生式继承:
与原型式继承非常相似,也是基于某个对象或某些信息创建一个对象,然后增强对象,最后返回对象。为了解决组合继续模式由于多次调用超类型构造函数
寄生组合继承:
集寄生式继承,和组合继承的优点于一身,是实现基于类型继承的最有效的方式
第七章 函数表达式
定义函数的两种方式
(1)函数声明
function functionname(arg0,arg1,arg2) {
//函数体
}
系统默认会函数声明提升,意思是在执行代码之前会先读取函数声明。可以把函数声明放在调用它的语句后面
(2)函数表达式
使用函数表达式可以无须对函数命名,从而实现动态编程。匿名函数,也成为拉姆达函数,是一种使用JavaScript函数的强大方式 。
特点:
(1)函数表达式不同于函数声明。函数声明要求有名字,但函数表达式不需要。没有名字的表达式也叫做匿名函数
(2)在无法确定如何引用函数的情况下,递归函数就会变得比较复杂
(3)递归函数始终调用arguments.callee来递归地调用自身,不要使用函数名-函数名可随时发生变化
递归:递归函数时一个在函数通过名字调用自身情况下构成的
例子:
function factorial(num) {
if (num<=1) {
return 1;
} else {
return num * arguments.callee(num-1); //return num*factorial(num-1)会出错
}
}
注:使用arguments.callee代替函数名,可以确保无论怎么调用函数都不会出问。因此,在编写递归函数时,使用arguments.callee总比函数名更保险
闭包:
(1)定义:闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的方式,就是在一个函数内部创建另一个函数。
(2)原理:
在后台环境中,闭包的作用域链包含着它自己的作用域、包含函数的作用域和全局作用域。通常,函数的作用域及其所有变量都会在函数执行结束被销毁。但是,当函数返回一个闭包时,这个函数的作用域将会一直在内存中保存到闭包不存在为止。
闭包可以在JavaScript中模仿块级作用域
(1)创建并立即调用一个函数,这样既可以执行其中的代码,又不会在内存中留下对该函数的引用。
(2)结果就是函数内存的所有变量都会被立即销毁—除非将某些变量赋值给了包含作用域
闭包还可以用于在对象中创建私有变量
(1)即使JavaScipt中没有正式的私有对象属性的概念,但可以使用闭包来实现公有方法,而通过共有方法可以访问在包含作用域中的定义变量
(2)有权访问私有变量的工会有方法叫搞特权方法
(3)看可以使用构造函数模式、原型模式来实现自定义类型的特权方法,也可以使用模块模式、增强的模块模式来实现单例的特权方法。
第八章 BOM
浏览器对象模型(BOM)以window对象为依托,表示浏览器窗口以及页面可见区域。同时windows对象还是EMCAScript中的Global对象,因而所有全局变量和函数都是它的属性,且所有原生的构造函数及其他函数都存在于它的名下。
全局作用域:
由于window对象同时扮演着EMCAScript中的Global对象的角色,所有在全局作用域中申明的变量、函数都会变成window对象的属性和方法。
定义全局变量与window对象上直接定义属性的区别: 全局变量不能沟通过delete操作符删除,而直接在window对象上的定义的属性可以。
例:
window.color = "red";
//在IE<9时抛出错误,在其他所有浏览器中都返回ture
delete window.color
窗口关系及框架
(1)在使用框架时,每个框架都有自己的window对象以及所有原生构造函数及其他函数的副本。每个框架都保存在frames集合中,可以通过位置或通过名称来访问。
(2)有一些窗口指针,可以用来引用其他框架,包括父框架
(3)top对象始终指向最外围的框架,也就是真个浏览器窗口
(4)parent对象表示包含当前框架的框架,而self对象则回指window
窗口位置
(1)获得窗口位置的方法:
var leftPos = (typeof window.screenLeft == "number")?
window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number")?
window.screenTop : window.screenY;
(2)移动窗口位置
1)window.moveTo() 参数: x 和 y 的坐标
2)window.moveBy() 参数: 水平和垂直方向上移动的像素
串口大小
(1)页面视口的大小 :
var pageWidth = window.innerWidth;
var pageHeight = window.innerHeight.;
if (typeof pageWidth !="number"){
if (document.compatMode=="CSS1Compat") {
pageWidth = document.documentElement.clientWidth;
pageHeight= document.documentElement.clientHeight;
} else {
pageWidth = document.body.clientWidth;
pageHeight = document.body.clientHeight;
}
}
(2)改变窗口大小
resizeTo() 参数:接收两个浏览器窗口的新宽度和新高度
resizeBy() 参数:接收新窗口与原窗口的宽度和高度之差
导航和打开窗口
(1)
window.open() 可以接收4个参数:要加载的URL、窗口目标、一个特性字符串以及一个表示新页面是否取代浏览器历史记录中当前加载页面的布尔值
例:
window.open("http://www.wrox.com/","Wrox.com/","height=400,width=400,top=10,left=10,resizable=yes");
(2)弹出窗口屏蔽程序 P202
间歇调用和超时调用
(1)超时调用
setTimeout()
参数:
第一个参数: 包含javaScript代码的字符串
第二个参数: 等待多长时间的毫秒数
清除:
clearTimeout();
(2)延时调用
setInterval()
第一个参数: 包含javaScript代码的字符串
第二个参数: 等待多长时间的毫秒数
清除:
clearInterval();
系统对话框
显示这些对话框时代码会停止执行,而关掉这些对话框后代码又会默认恢复
(1)alert() 系统对话框
(2)confirm() 系统确认框
(3)promt() 提示框
location对象
通过编程方式访问浏览器的导航系统,设置相应的属性,可以逐段或整体性地修改浏览器的URL。
(1)位置操作
location.assign("http://www.wrox.com")
window.location = "http://www.wrox.com ";
location.href = "http://www.wrox.com";
最常用的为location.href;
(2)禁止后退
location.replace("http://www.wrox.com");
navigator对象
提供了浏览器有关信。到底提供哪些信息,很大程度上决定于浏览器;不过也有一些公共的属性存在所有浏览器中
screen对象
保存着与客户端显示器有关的信息,这些信息一般用于站点分析
history对象
浏览器的历史记录打开一个小缝隙,开发人员可以根据此判断记录的数量,也可以在历史记录中向后或向前导航到任何页面
history.go(-1) //后退一页
history.go(2) //前进两页
history.go("wrox.com");
history.go("nczonline.net");
history.back();
history.forward();
第九章 客户端检测
客户端检测是JavaScipt开发中最具争议的一个话题。由于浏览器间存在差别,通常需要根据不同浏览器的能力分别编写不同的代码。
(1)能力检测:在编写代码之前先检测特定浏览器的能力。例如,脚本在调用某个函数之前,可能要先检测该函数是否存在。这种检测方法将开发人员从考虑具体的浏览器类型和版本中解放出来,让他们把注意力集中到相应的能力是否存在上。能力检测无法精确地检测特定的浏览器版本。
(2)怪癖检测:怪癖实际上市浏览器实现中存在的bug。怪异检测通常涉及到运行一小段代码,然后确定浏览器是否存在某个怪癖。由于怪癖检测与能力检测相比效率地低,因此应该只在某个怪癖会干扰脚本运行的情况下使用。怪癖检测无法精确地检测特定的浏览器和版本
(3)用户代理检测:通过检测用户代理字符串来识别浏览器。用户代理字符串中包含大量与浏览器有关的信息,包括浏览器、平台、操作系统及浏览器版本。
在决定使用哪种客户端检测方法时,一般优先考虑使用能力检测。怪癖检测是确定应该如何处理代码的第二选择。而用户代理检测时客户端检测的最后一种方案,因为这种方法对用户代理字符串具有很强的依赖性。