读书笔记-JavaScript面向对象编程(一)
前前后后大概花了两周的时间,终于把这本书大致看完了,对之前javascript高级程序设计中模糊不清的概念,有了一些新的看法和角度,整体上来说,本书还是一本比较适合有一定前端基础的朋友们阅读。参考http://pan.baidu.com/s/1eSDSTVW 密码: 75jr
第1章 引言
1.1 回顾历史
1.2 变革之风
1.3 分析现状
1.4 展望未来
1.5 面向对象的程序设计
1.5.1 对象(属性和方法的集合)
1.5.2 类 (相似对象的共同特征,如麻雀、老鹰都是鸟类)
1.5.3 封装 (将属性和方法集合起来,也有封闭作用域的概念,如封装一个播放器对象)
1.5.4 聚合 (将几个对象合并成一个对象)
1.5.5 继承 (一个实例对象继承父级对象的一些属性和方法)
1.5.6 多态 (一个对象调用其他对象的方法,call和apply)
1.6 OPP概述
1.7 训练环境设置
1.8 使用Firebug控制台
1.9 本章小结
第2章 基本数据类型、数组、循环及条件表达式
2.1 变量 (命名规则、声明前置、作用域)
2.2 操作符 (+、-、*、/、%、++、--、=、+=、-=、*=、/=、%=)
2.3 基本数据类型 (数字、字符串、布尔值、undefined、null)
2.3.1 查看类型操作符 typeof
2.3.2 数字(整数或浮点数,typeof返回number,八进制0开头,十六进制0x开头,指数表示法1e+1=10,2e-3=0.002)
(Infinity无穷大不可运算,typeof NaN也是number,NaN具有传染性即带入运算结果为NaN)
2.3.3 字符串(单双引号之间的任何值,typeof返回string,*1或parseInt转换为数字)
(\转义字符,\n换行符,\r回车符,\t制表符,\u后面为Unicode码)
2.3.4 布尔值(typeof返回boolean,逻辑运算符!、&&、||会默认转换,6个falsy["",null,undefined,0,NaN,false])
(比较运算符==、===、!=、!==、>、>=、<、<=,NaN不等于任何包括自己)
2.3.5 undefined和null(不存在或未赋值的变量时得到undefined,null需要手动赋值,数字转换:undefined为NaN,null为0)
2.4 基本数据类型综述
2.5 数组(typeof返回object)
2.6 条件与循环
2.6.1 if条件表达式 (if(a)如果a未定义会产生警告,可以用if(typeof a !=="undefined"),用三元运算符代替?:)
(switch语句,case比对为true执行冒号后语句, break跳出switch[可选],default可选)
2.6.2 循环(while、do while、for、for in不可代替,遍历数组或对象【此处可深入跟forEach和each比较】)
2.7 注释(单行//,多行/**/)
2.8 本章小结
2.9 练习题
1、如果我们再控制台中执行下列语句,结果分别是什么?为什么?
var a; typeof a //undefined var s='1s';s++ //NaN,自增自减必须针对Number类型(区别s+=1,值为'1s1') !!'false' //true,'false'转换为true,两次取反还为true !!undefined //false typeof -Infinity //number 10 % '0' //NaN undefined==null //true,默认转换为false==false为true false==='' //false typeof '2E+2' //string a=3e+3;a++ //3000,a++本行取值为a,下一行为a+1
2、执行下面的语句后,v的值会是什么?
>>> var v = v || 10;
如果将v分别设置为100、0、null,或者卸载它(即delete v),结果又将是什么?
var v=v||10; //v=10,undefined默认转换为false v=100;v=v||10; //v=100 v=0;v=v||10; //v=10,0默认转换为false v=null;v=v||10; //v=10,null默认转换为false delete v;v=v||10;//v=10,delete后为undefined(同上第一行)
3、编写一个打印乘法口诀表的脚本程序。(提示:使用嵌套循环来实现。)
var res="\n"; for(var i=1;i<=9;i++){ for(var j=1;j<=i;j++){res+=i+"*"+j+"="+i*j+" "} res+="\n" } console.log(res) /* 1*1=1 2*1=2 2*2=4 3*1=3 3*2=6 3*3=9 4*1=4 4*2=8 4*3=12 4*4=16 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81 */
第三章:函数
3.1 什么是函数 (一组代码)
3.1.1 调用函数
3.1.2 参数(已定义形参,少传实参默认undefined,多传被忽略,也可使用内建的arguments)
3.2 预定义函数
3.2.1 parseInt()(转换为整数,第二个参数可选:设置进制类型,一般默认十进制,0x开头默认16,0开头默认8)
3.2.2 parseFloat()(转换为十进制浮点数,可接受指数形式"123e-2"为1.23)
3.2.3 isNaN()(确定是否为数字,因为NaN===NaN为false不可用)
3.2.4 isFinite()(检测是无穷大Infinity返回false否则为true,isFinite(NaN)返回false)
3.2.5 URI的编码与反编码(encodeURI()、encodeURICompent()和反转函数decodeURI()、decodeURICompent())
3.2.6 eval()(将字符串当做JS脚本来执行)
3.2.7 alert()(不解释)
3.3 变量的作用域(注意:没有块级作用域;不用var声明默认为全局变量;声明前置)
3.4 函数也是数据(typeof function(){}返回function,函数是赋值给变量的一种数据,只是含代码和可调用)
3.4.1 匿名函数(可以作为参数传递个其他函数[回调函数],用来执行一次性任务[自调函数])
3.4.2 回调函数(可以传递匿名函数减少全局变量,可以将一个函数调用委托给另一个函数,提升性能)
3.4.3 回调示例(如下修改后只需要一次函数调用就够了,使用匿名函数代替addOne)
//两个函数共同处理时的数据传递 function multiplyBytwo(a,b,c){ var i,ar=[]; for(i=0;i<3;i++){ar[i]=arguments[i]*2;} return ar; } function addOne(a){return a+1;} var myarr=multiplyBytwo(10,20,30) for(var i=0;i<3;i++){myarr[i]=addOne(myarr[i])} myarr //[21,41,61]
//回调函数方式 function multiplyBytwo(a,b,c,callback){ var i,ar=[]; for(i=0;i<3;i++){ar[i]=callback(arguments[i]*2);} return ar; } var myarr=multiplyBytwo(10,20,30,function(a){return a+1;})
myarr //[21,41,61]
3.4.4 自调函数(封闭作用域,不产生全局变量,缺点不可重复调用)
3.4.5 内部私有函数(函数内部的函数:减少命名冲突;私有化)
3.4.6 返回函数的函数(return返回一个函数)
3.4.7 能重写自己的函数(即为函数重新赋值)
3.5 闭包
3.5.1 作用域链(没有块级作用域,只有函数作用域,函数内可访问自身和父级作用域中变量,函数外不可访问函数内私有变量)
3.5.2 词法作用域(每个函数定义时创建自己的环境即作用域)
function f1(){var a=1;f2()} function f2(){return a} f1()//a is not defind 变量a是f1函数的私有变量,f2被定义时(不是执行)为全局函数,它无法在全局作用域中找到私有变量a
3.5.3 利用闭包突破作用域链(在函数内部传递或返回给全局空间)
function f(){var a=1; return function(){ return a}} var n=f(); n(); //1,内部匿名函数可访问私有变量a,返回这个匿名函数,将它赋值给n,然后执行n,即可访问私有变量a
var n; function f(){var a=1;n=function(){ return a}} f();n()//1,定义一个全局变量n,执行f()后在内部定义了n可以访问内部变量,同时没有用var它是属于全局
function f(a){var n=function(){ return a};a++;return n} var m=f(123) m()//124返回++更新后的值,n前面是赋值而调用执行是return的时候,故函数绑定的是作用域本身,不是变量或变量当前返回值
//循环中的闭包 var arr=[]; for(var i=0;i<3;i++){ arr[i]=(function(x){return x})(i) } arr[0]//0利用自调函数将i赋值给局部变量x,来避免调用作用域本身(即i更新后的值3)
3.5.4 Getter与Setter(两个额外函数用来访问和设置不想暴露给外部的私有变量)
3.5.5 迭代器
function setup(arr){ var i=0; return function(){ return arr[i++]} } var next=setup(['a','b','c']); next()//a next()//b next()//c
3.6 本章小结
3.7 练习题
1、编写一个将十六进制值转换为颜色的函数,以蓝色为例#0000FF应被表示成‘rgb(0,0,255)’,然后将函数命名为getRGB()
function getRGB(color){ var rgb=[parseInt('0x'+color.slice(1,3)),parseInt('0x'+color.slice(3,5)),parseInt('0x'+color.slice(5,7))]; return 'rgb('+rgb[0]+","+rgb[1]+","+rgb[2]+")"; } getRGB("#00ff00")//"rgb(0,255,0)"
2、如果在控制台中执行以下各行,分别会输出什么内容?
parseInt(1e1)//10 parseInt('1e1')//1,遇到不明字符截止 parseFloat('1e1')//10,可接受指数类型 isFinite(0/10)//true isFinite(20/0)//false isNaN(parseInt(NaN))//true
3、下面代码中,alert弹出的内容是什么?(2)
var a=1; function f(){ var a=2; function n(){alert(a)} n() } f()//2
4、以下所有示例都会弹出“Boo!”警告框,请解释其中的原因?
var f=alert; eval('f("Boo!")')//将内置alert赋值给f,再用eval编译,等同直接alert
var e,f=alert; eval('e=f')('Boo!')//e=f=alert
(function(){ function(){return alert} })()('Boo!')//自调函数返回alert
第4章 对象
4.1 从数组到对象(数组等于数字键值的对象,对象的键值可以不加引号,除了js保留字数字开头或者特殊字符外)
4.1.1 元素、属性、方法(数组元素、对象属性,若属性为函数则称为方法)
4.1.2 哈希表、关联型数组(即对象)
4.1.3 访问对象属性(点语法a.b和中括号语法a[b],中括号语法适用于属性名为变量)
4.1.4 调用对象的方法(同属性和调用函数相同,a.b()或a[b]())
4.1.5 修改属性与方法
4.1.6 使用this值(对象方法内部,可用this代替这个对象,即当前对象的意思)
4.1.7 构造器函数(使用new操作符,可以在创建同时接受一些参数)
4.1.8 全局对象(全局属性和函数,,默认为浏览器(window)宿主对象的属性和方法)
4.1.9 构造器属性(字面量法创建的对象,constructor默认为Object())
function Hero(name){this.name=name;} var h2=new Hero("aaa") var h3=new h2.constructor("bbb") h3.name //bbb,h2.constructor===Hero
4.1.10 instranceof操作符(返回一个对象是不是摸个指定构造器所创建的,如a={},a instanceof Object//true)
4.1.11 返回对象的函数(工厂模式)
function factory(name){ return { name:name} } var o=factory('one') o.name//"one" o.constructor//Object()
function C(){this.a=1} var c=new C() c.a//1 function C2(){this.a=1;return {b:2}} var c2=new C2() c2.a//undefined,这里构造器返回的不再是包含a的this对象 c2.b//2,而是return返回的对象(仅在构造函数return返回对象时发生,若返回非对象类型,仍然返回this对象)
4.1.12 传递对象(复制对象传递的是引用,修改将影响它所引用的原对象 )
4.1.13 对象比较(两个对象引用相同对象时为true,如果不同对象,即使方法属性相同也为false)
4.1.14 Firebug控制台中的对象
4.2 内建对象
4.2.1 Object(所有对象的父级对象,空对象默认含有constructor属性,toString和Valueof方法)
4.2.2 Array(数组也是对象,所以继承了Object的属性和方法,数组长度length可设置,超出则创建undefined,小于则多余被移除)
(数组的特有方法:push添加、pop减少、sort排序、join字符串连接、slice截取、splice替换)
4.2.3 Function(函数也是对象,默认属性constructor和prototype,特有方法call和apply,arguments类数组它的callee返回自身,用于匿名递归调用)
4.2.4 Boolean
4.2.5 Number(特有方法:toFixed、toPrecision、toExponential)
4.2.6 String(方法:toUpperCase、toLowerCase、charAt、indexOf、lastIndexOf、slice和substring、split、concat)
4.2.7 Math(属性为常量不可修改,方法random、floor、ceil、max、min、pow、sqrt、sin、cos、atan。。)
4.2.8 Date
4.2.9 RegExp(两种匹配内容的方法test、exec,以正则表达式为参数的字符串方法match、search、replace、split)
4.2.10 Error(使用try、catch及finally处理错误,throw new RangeEror抛出自建错误对象)
4.3 本章小结
4.4 练习题
1、请看下列代码,请问这里的的this指向的是全局对象还是对象o?
function F(){ function C(){return this;}//函数执行默认为window调用,this指window全局对象 return C();//C()执行并返回了window } var o=new F();//当构造函数返回对象时,新建对象等于返回的对象,所以o===window
2、下面代码执行的结果是什么?
function C(){this.a=1;return false;} console.log(typeof new C()) //object,new C()等于创建了一个对象
3、下面这段代码的执行结果又将是什么?
c=[1,2,[1,2]]; c.sort();//[1,[1,2],2] c.join('--');//'1--1,2--2' console.log(c);//[1,[1,2],2]
4、在String()构造器不存在的情况下自定义一个MyString()的构造器函数。并要让创建的对象通过以下测试:
var MyString=function(str){this.str=str;this.init()} MyString.prototype={ constructor:MyString, init:function(){ var that=this; for(var i in that.str){that[i]=that.str[i]} that.length=+i+1; }, toString:function(){return this.str}, valueOf:function(){return this.str}, charAt:function(n){return isNaN(Number(n))?this[0]:this[Number(n)]}, concat:function(s){ return this.str+s}, slice:function(a,b){ var s=''; b=b>0?b:this.length+b; for(var i=a;i<b;i++){s+=this[i]} return s; }, split:function(s){ var str='',arr=[]; for(var i=0;i<this.length;i++){if(this[i]==s){arr.push(str);str=''}else{str+=this[i];}} arr.push(str) return arr; } } var s=new MyString('hello') s.length //5 s[0] //h s.toString() //hello s.valueOf() //hello s.charAt(1) //e s.charAt('2') //l s.charAt('e') //h s.concat(' world!') //hello world! s.slice(1,3) //el s.slice(0,-1) //hell s.split('e') //["h","llo"] s.split('l') //["he","","o"]
5、更新上面的MyString()构造器,为其添加一个reverse()方法
MyString.prototype.reverse=function(){ var str=''; for(var i=this.length-1;i>=0;i--){str+=this[i]} return str; }
6、在Array()构造器以及相关数组的文本标示法都不存在的情况下,自定义一个类似的MyArray()构造器,并令其通过以下测试;
var MyArray=function(arr){this.arg=arguments;this.init()} MyArray.prototype={ constructor:MyArray, init:function(){ var that=this; for(var i in that.arg){that[i]=that.arg[i];} that.length=+i+1; }, toString:function(){ var that=this,str=''; for(var i=0;i<that.length;i++){str+=(that[i]+[i==(that.length-1)?'':','])} return str; }, push:function(s){this[this.length]=s;this.length++;return this.length;}, pop:function(){ this.a=[];this.length--;delete this[this.length]; for(var i=0; i<this.length;i++){this.a[i]=this[i]};return this.a}, join:function(b){var that=this,str=''; for(var i=0;i<that.length;i++){str+=(that[i]+[i==(that.length-1)?'':b])} return str;} } var a=new MyArray(1,2,3,'test') a.toString() //1,2,3,test a.length //4 a[a.length-1] //test a.push('boo') //5 a.toString() //1,2,3,test,boo a.pop() //[1,2,3,test] a.join(',') //1,2,3,test a.join(' isn\'t ') //1 isn't 2 isn't 3 isn't test
7、在Math对象不存在的情况下,创建一个类似的MyMath对象,并为其添加以下方法:
◆ MyMath.rand(min,max,inclusive)--随机返回min到max区间中的一个数,并且在inclusive为true时为闭区间(默认)
◆ MyMath.min(array)返回目标数组中的最小值
◆ MyMath.max(array)返回目标数组中的最大值
var MyMath={ rand:function(min,max,inc){ var i=true;if(!arguments[2]){i=false;} function r(n){return Math.floor((new Date().getTime()*9301+49297)%233280/233280*n);} if(i){return r(max-min+1)+min;}else{return r(max-min)+min;} }, sort:function(arr,f){ var l=arr.length,temp=arr[0]; if(l>=2){for(var i=1;i<l;i++){temp=(temp-arr[i])*f>0?temp:arr[i];}} return temp; }, min:function(array){return this.sort(array,-1)}, max:function(array){return this.sort(array,1)} } console.log(MyMath.rand(5,10,true))//随机5-10 console.log(MyMath.min([131,53,21]))//21 console.log(MyMath.max([88,44,99]))//99