第八章 避免“空比较”
8.1 检测原始值
对于字符串,typeof 返回 “string”
对于数字,typeof 返回 “number”
对于布尔值,typeof 返回 “bo'olean”
对于undefined,typeof 返回 “undefined”
typeof 的基本语法
typeof variable
或
typeof(variable)
8.2 检测引用值
因为typeof variable 当 variable 为null 时 返回的时object,故不能用typeof 来检测null
value instanceof constructor
例:
//检测日期
if(value instanceof Date){
condole.log(value.getFullYrar());
}
//检测正则表达式
if(value instanceof RegExp){
if(value.test(anotherValue)){
condole.log("Matches");
}
}
//检测Error
if(value instanceof Error){
throw value;
}
instanceof 运算符也可用于检测自定义类型,并且时唯一可检测自定义类型的方法
8.2.1 检测函数
· 用typeof
8.2.2 检测数组
function isArray(value){
return Object.prototype.toString.call(value) === "[object Array]";
}
已被基本库添加
function isArray(value){
if(typeof Array.isArray === "function"){
return Array.isArray(value);
}else{
return Object.prototype.toString.call(value) === "[object Array]";
}
}
8.3 检测属性
var object = {
count:0,
related:null
}
if("count" in object){
// 这里的代码会执行
}
第九章 将配置数据从代码中分离出来
9.1 什么是配置数据
配置数据是应用中写死的值
9.2 抽离配置数据
var config = {
MSG_INVALID_VALUE:"invalid value",
URL_INVALID:"/errors/invalid.php",
CSS_SELECTED:"selected"
}
function(value){
if(!value){
alert(config.MSG_INVALID_VALUE);
location.href = config.URL_INVALID;
}
}
function(element){
if(hasClass(element,config.CSS_SELECTED)){
removeClass(element,config.CSS_SELECTED);
}else{
addClass(element,config.CSS_SELECTED);
}
}
9.3 保存配置数据
第十章 抛出自定义错误
10.1 错误的本质
错误常在非期望的地点,不适当的跳出来
10.2 再javascript中抛出错误
10.3 抛出错误的好处
抛出自己的错误可以使用确切的的文本供浏览器显示
function getDivs(element){
if(element&&element.getElementsByTagName){
return element.getElementsByTagName("div");
}else{
thow new Error("getDivs():Argument must be a DOM element.")
}
}
10.4 何时抛出错误
一旦修复了一个很难调试的错误,尝试增加一两个自定义错误。
如果正在编写代码,思考一下:如果某些事情发生会很招糕,就抛出一个错误
如果正在编写别人的编写的代码,思考一下他们的使用方式,再特定的情况下抛出错误
10.5 try-catch
try {
somethingThatMightCauseAnError();
} catch (ex){
handleError(ex)
} finally {
continueDoingOtherStuff();
}
10.6 错误类型
Eroor
所有错误的基本类型。实际上引擎从来不会抛出该类型的错误。
EvalError
通过eval()函数执行 代码时发生错误时抛出
RangeError
一个数字超出它的边界时抛出——例如:试图创建一个长度为-20的数组。
ReferenceError
期望的对象不存在时抛出——例如,试图在一个null对象
SyntaxError
给eval()函数传递的代码中有语法错误时抛出
TypeError
变量不是期待的类型时抛出。例如,new10 或 “prop” in true.
URlError
给encodeURl(),encodeURlComponent(),decodeURl()或者decodeURlComponent()等函数传递格式非法的URl支付窜的抛出
创建自定义错误类型
function MyError (message) {
this.message = message;
}
MyError.prototype = new Error();
try {
// 有些代码引发了错误
} catch (ex) {
if(ex instanceof MyError){
// 处理自己的错误
}else{
// 其他处理
}
}
第十一章 不是你的对象不要动
11.1 什么是你的
如果你的代码没有创建这些对象,不要修改它们,包括
*原生对象(Object,Array等等)
*DOM对象(如document)
*浏览器对象模型(BOM)对象(例如:window)
*类库对象
11.2 原则
对待已经存在的对象
*不覆盖方法
*不新增方法
*不删除方法
11.2.1 不覆盖方法
浪费大量时间来排查问题
11.2.2 不新增方法
如果想修改,最佳最可维护的方式时创建一个插件
11.2.3 不删除方法
删除方法可能导致以前正常运行的代码报错
11.3 更好的途径
11.3.1 基于对象的继承
例如:
var person = {
name:"Nicholas",
sayName: function(){
alert(this.name);
}
}
var myPerson = Object.create(person);
myPerson.sayName(); // 弹出"Nicholas"
myPerson.sayName = function() {
alert("Anonymous");
};
myPerson.sayName(); // 弹出"Anonymous"
person .sayName(); // 弹出"Nicholas"
Object.create()方法可以指定第二个参数,该参数对象中的属性和方法将添加到新的对象中
例如:
var myPerson = Object.create(person,
name:{
value:"Greg"
}
);
myPerson.sayName(); // 弹出"Greg"
person .sayName(); // 弹出"Nicholas"
一旦以这种方式创建了一个新对象,该新对象完全可以随意修改。
11.3.2 基于类型的继承
function MyError (message) {
this.messagfe = message;
}
MyError.piototype = new Error();
var error = new MyError("something bad happened. ");
console.log(error instanceof Error); // true
console.log(error instanceof MyError); // true
构造器继承是调用超类的构造函数时传入新建对象作为其this的值
例如:
function Person (name) {
this.name ;
}
function Author (name) {
Person.call(this,name); // 继承构造器
}
Author.prototype = new Person();
11.3.3 门面模式
下面是一个DOM对象包装器代码示例:
function DOMWrapper (element) {
this.element = element;
};
DOMWrapper.prototype.addClass = function (className) {
element.className += " " + className;
};
DOMWrapper.prototype.remove= function () {
this.element.parentNode.removeChild(this.element);
};
// 用法
var wrapper = new DOMWrapper(document.getElementByid("my-div"));
// t添加一个className
wrapper.addClass("selected");
// 删除元素
wrapper.remove();
11.4 关于Polyfill 的注解
尽量用门面模式解决一些问题,尽量少使用Polyfill
11.5 阻止修改
例子:
var person = {
name:"Nicholas"
}
// 锁定对象
Object.preventExtension(person);
console.log(object.isExtensible(person)); // false 不可扩展
person.age = 25; // 正常情况悄悄地失败,除非再strict模式下抛出错误
可以使用 Object.isSealed()函数来检测一个对象是否密封
// 锁定对象
Object.seal(person);
console.log(object.isExtensible(person)); // false 不可扩展
console.log(object.isSealed(person)); //true
delete person.name; // 正常情况悄悄地失败,除非再strict模式下抛出错误
person.age = 25; // 正常情况悄悄地失败,除非再strict模式下抛出错误
当一个对象密封时,它已存在的属性和方法不能被删除
使用Object.freeze()函数来冻结一个对象,可以使用Object.ifFreezen()函数来检查一个对象是否已经被冻结
被冻结的对象同时也是不可扩展和被密封的