编写可维护javascript学习笔记4

第八章 避免“空比较”

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()函数来检查一个对象是否已经被冻结
	
	被冻结的对象同时也是不可扩展和被密封的

你可能感兴趣的:(读后感)