Javascript高级程序设计 学习笔记

一、数据类型

5种基本数据类型:string, number,Boolean,undefined,null
复杂数据类型:object
1.undefined
声明未赋值为undefined,未声明的变量只能进行一种操作:用typeof检测数据类型为undefined,
但它确实不等于undefined
2.null
null是一个空对象指针,所以typeof(null)=object,undefined派生于null,
所以(null==undefined)=true,
(null===undefined)=false.
bool值为false的情况:空字串,0和nan,null,undefined
3.number
nan的任何操作都为nan,与任何值都不相等,包括它本身。
isNaN(任何类型的参数):判断是否“不是nan”,会尝试将参数转换为数组,不能转换的值为true(不是数值)
数值转换:
Number(参数):
参数:
(1)bool->0,1
(2)null->0
(3)null->0,undefined->nan
所以isNaN(null)=false,isNaN(undefined)=true
(4)string:只含数字(包括浮点)的转为其所包含的数字,首个数字为0则忽略,包含十六进制会转成10进制,空串转为0,其余为NaN
parseInt(参数):
与Number区别:
parseInt(串)=NaN,
parseInt(“123BLUE”)=123,
Number(“123BLUE”)=NaN
parseFloat:类似parseInt
4.string
除了null和undefined之外,其余类型都有toString()方法,且不需传参数,

二、变量、作用域与内存空间

1.引用变量和值变量
string, number,Boolean,undefined,null为值类型,按值访问,前后赋值时其实是创建一个值的副本,每个变量都占一个内存空间,不会互相影响。保存在栈内存中。
数组、对象、函数为引用类型,原型都为object,值保存在内存中,js无法对内存直接操作,所以操作对象是值的引用。前后赋值是在改变的值指向同一个地址,所以会互相影响。保存在堆内存中,复制时其实是复制指针,指向同一个对象。
可以用typeof区分值类型,用instanceof区别引用类型:
引用类型instanceof Array/Object/Function
2.参数传递
参数只能按值传递,参数在函数外部和内部等同于两个值,不会互相影响,即函数的参数相当于局部变量。
3.块级作用域
Js没有块级作用域。使用var声明变量时会被添加到最近的环境中,有两种环境全局环境和函数环境。若初始时没有用var声明会被添加到全局变量,但在严格模式下会报错。
4.作用域链
只能向上搜索,局部环境有权访问函数作用域的变量,包括父环境及全局环境。
全局环境只能访问全局变量,无权访问局部变量。
5.垃圾回收机制
1)标记清除:垃圾收集器会给内存中的所有变量打上标签,去掉环境变量以及被环境中的变量引用的变量(闭包),剩下的即要清除的。
2)引用计数:释放引用次数为0的值所占的内存。但循环引用即使执行完毕引用依然不为0,所以要手动解除引用。

三、引用类型

Array类型
1.检测数组:Array.isArray(数组名) 数组名instanceof Array
2.转换方法
1)数组.toString(),toLocalString():返回由数组中每个值以字符串形式组成的以逗号间隔的字符串
2)数组.ValueOf():返回字符串
3)数组.join(“分隔符”):返回以给定分隔符为间隔的字符串,默认为逗号。
3.栈、队列方法
Push:向数组末端添加项,返回数组长度。
Pop:移除最后一项,返回移除的值。
Shift:移除第一项返回移除的值。
Unshift:在前端添加任意项,返回长度。
4.排序方法:
Reverse():反转数组
Sort():调用toString方法,比较得到的字符串,有时会出错,可接受一个比较函数作为参数进行排序。

//升序:
Sort(function(val1,val2){
If(val1<val2)
{return -1;}
Else if(val1>val2){
Rreturn 1;}
Else return 0;
})

5.操作方法
1)数组1.concat(数组2):返回两数组的链接:数组1+数组2
2)slice:数组.Slice[start,end):返回截断的数组,左闭右开,若无end参数,则默认截至到末尾,若start为负数,可看作数组长度加start.
3)splice:
删除:splice(index,count):从index处开始删除count个元素,返回删除的项
插入:splice(index,0,item1,…itemx) 0意为删除0个元素,返回一个空数组
替换:splice(index,conut,item1,…itemx) 返回被替换掉的项

6.查找方法
IndexOf(查找项,起始位置):返回索引,不存在则返回-1
LastindexOf():从数组末尾开始查找。
7.迭代方法:
Some(),filter(),forEach(),map(),every():它们的参数(function(item,index,arr){})
8.归并方法
Reduce():遍历所有项
参数:function(prev,cur,index,arr)
Date类型(略)

RegExp类型
/g:全局模式,匹配所有字符串
/i:不区分大小写
/m:多行模式

Fuction类型

  1. 将函数名是一个包含指针的变量,函数没有重载,相同的函数名后面声明的会覆盖前面。
  2. 函数声明无变量提升,函数表达式有
  3. Arguments对象:保存函数参数,函数可以接受任意个参数,可以通过arguments[]来访问,函数长度是参数的长度即argument.length.
    Arguemnts.callee()指向拥有这个arguments对象的函数,即函数名,但在严格模式下会报错。
  4. this指向的是函数的执行环境,全局环境this对象引用的是window,当函数是某个对象的调用方法时,this就等于那个对象。匿名函数的执行环境具有全局性,this为window
    Caller属性:函数名.caller/arguments.callee.caller返回调用当前函数的函数
  5. call和apply方法:改变函数的作用域 fx.call()/fx.apply()
    apply(var1,var2):var1运行函数的作用域,var2:参数数组,可以是数组,也可以是arguments对象,将运行作用域改为var1
    Call(var1,var2):var1同apply,var2:参数直接传递,每个都必须列举出来。
    函数.Call/apply(window):显示得在全局作用域中调用函数
    函数.Call/apply(this):this绑定作用域,函数在该作用域下运行
Window.color=”red”;
Var o={color:”blue”};
Function saycolor(){
Alert(this.color);
}
Saycolor();//red
Saycolor.apply(this);//red
Saycolor.apply(window);//red
Saycolor.apply(o);//blue
Var osaycolor=saycolor.bind(o);
Osaycolor();//blue

Bind(var1):创建一个函数实例(也是函数),this的值会与var1绑定

基本包装类型
String

  1. 字符方法:charAt(index),charCodeAt(index):返回index处的字符和字符编码。与字符串[index]访问相同

  2. 操作方法
    Concat:连接
    创建新字符串
    在这里插入图片描述

  3. 位置方法
    IndexOf(item,start):从index开始寻找item,start默认为0,返回index.
    LastIndexOf(item,start):从末尾开始寻找
    只能找到一个,不能全找到
    Trim():删除前缀和后缀的所有空格,返回副本,原字符串不变
    ToUpperCase,toLowerCase:字符串转换为大小写。

Math.floor(math.random()*(max-min+1)+min)

四、面向对象的程序设计

创建对象

  1. 工厂模式
Function createPerson(name,age,job){
Var o=new Object();
o.name=name;
o.age=age;
o.job=job;
o.sayname=function(){
alert(this.name)};
return o;
}
Var person1=createPerson(“jane”,18,“student”);
  1. 构造函数模式
Function Person(name,age,job){
This.name=name;
This.age=age;
This.job=job;
This.sayname=function(){
Alert(this.name);}

}
Var person1=new Person(‘”jane”,18,”student”);

New过程:
1) 创建一个对象实例。
2) 将构造函数的作用域赋给新对象实例,this指向新对象实例
3) 执行构造函数,为对象实例添加属性方法。
4) 返回新对象。
对象实例有一个constructor指针指向构造函数
如person1.constructor=Person
Person1 instanceof Persontrue
Person1 instanceof Object
true//所有的对象均继承自Object.
构造函数可当成普通函数使用(不加new),this指向window。
可通过call/apply在另一对象作用域中调用。
缺点:每个实例的方法都会重复创建(因为函数也是对象),所以方法可放在函数外定义,但封装性不好。
3. 原型模式

Function Person(){}//构造函数
Person.prototype.name=”jane”;
Person.prototype.age=18;
Person.prototype.job=”student”;
Person.prototype.sayname=function(){
Alert (this.name);};
//字面量创建原型方法
Function Person(){}//构造函数
Person.prototype={
Constructor:Person;//若不说明,则constructor指向Object
Name:”jane”;
Age:18;
Job:”student”;
Sayname:function(){
Alert (this.name);}
};

Var person1=new Person();
Person1.sayname();//jane

在这里插入图片描述

构造函数有一个prototype指针指向函数原型Person.prototype,函数原型也有个Person.prototype.constructor指针指向构造函数,所有的方法属性在对象原型中添加。当调用构造函数创建一个实例后,对象实例和构造函数无直接关系,它也有一个prototype指针指向原型对象,原型对象中的所有方法属性都能被所有对象实例共享。
读取对象实例的某个属性后,会从实例本身开始搜索该属性,如不存在再继续搜索指针指向的原型。如果再实例中添加一个同名对象,该属性会先屏蔽原型中属性,但原型的属性仍然存在。
实例.hasOwnPrototype(“属性”):可查看该属性是否属于实例本身,不是来自于原型,返回bool值
“属性”in实例:返回bool值,无论该属性存在于实例还是原型中。
Object.key(对象):返回包含所有可枚举属性的字符串数组。如果通过实例调用,只能返回实例自身的属性。
原型具有动态性:即使先创建实例再修改原型,仍然能准确访问,但是重写整个原型对象则会产生错误,因为将原型修改为另一对象等同于切断了实例和原型的联系。
缺点:虽然同名属性会屏蔽原型属性,但是每个实例对原型中引用类型的属性修改会互相影响。
解决:组合使用构造函数模式和原型模式
构造函数用于定义实例属性和引用类型属性,原型用于定义方法和共享属性。

Function Person(name,age,friend){
This.name=name;
This.age=age;
This.friend=[“kk”,”mc”];
}
Person.prototype={
Constructor:Person;
Sayname:function(){
Alert(this.name);}
};

4.原型链
1)

Function Super(){
This.property=true;
}
Super.prototype.getval=function(){
Return this.property;
}	
Function Sub(){
This.subproperty=false;
}
Sub.prototype=new ppSuper();//sub原型对象是super的实例
Sub.prototype.getsubval function(){
Return this.subproperty;
}
Var o=new Sub();

因为sub继承super,所以未使用sub默认提供的原型,而是换上一个新原型,这个新原型是super的实例,作为实例它和普通实例一样有一个prototype指针指向构造函数的原型。Sub继承super的所有方法属性,super的实例属性被添加到sub的原型中。

在这里插入图片描述

所有函数的默认原型都是Object的实例,Object.prototype是原型链的顶端。

在这里插入图片描述

存在的问题:1)父类super的所有原型实例都会有自己的引用属性,但是子类的实例共享一个引用属性,修改会互相影响。(从继承父类(原型属性的继承)独自拥有,从子类继承(实例(子类也是实例)属性的继承)共享)
2)不能向父类的构造函数传递参数

2)解决方法:
借用构造函数:在子类构造函数内部调用父类构造函数
Function Sub(){
Super.call(this);}
Var o=new Sub();//结合new过程第二步:this指向o,执行构造函数,同过call(this)在对象o上执行Super构造函数,sub的实例不经过sub的构造函数直接调用父类super的构造函数,从而拥有自己的引用属性副本。传递参数也可以通过这种方法实现,如:super.call(this,”jane”)

3)组合继承
使用原型链实现原型属性和方法的继承,把实例属性放在构造函数里然后通过借用构造函数实现对实例属性的继承。
4)寄生组合式继承(存疑)
通过借用构造函数继承属性,原型链的混合模式继承方法。不必两次调用父类的构造函数,省去了创建子类原型的调用。

五、函数表达式

1.递归:用原函数名实现递归,当函数名被更改时会出错(因为函数是引用类型),可以用arguments.callee代替函数名,但在严格模式下会出错,可以将整个递归函数赋值给一个变量。
2.函数调用过程
当函数fx被调用时,会创建一个执行环境和相应的作用域链。作用域链首端是该函数的活动变量,包括arguments和其他命名参数,后一位是外部函数的活动对象等等,直至作为全局执行环境的全局变量对象。全局变量始终存在,函数内的活动对象在函数执行完就被销毁,只在函数执行过程中存在。作用域链实际是一个指向变量对象的指针列表。
但闭包情况又有所不同
3.闭包
闭包指在函数内部创建另一个函数,它有权访问另一函数作用域内的变量。闭包的作用域处理其自身活动变量和全局变量之外,还包括其外部函数的活动变量,所以它就有权访问其外部函数的变量。当外部函数执行完后,它的活动对象也不会被销毁。因为闭包正在引用它的活动对象,也就是其执行环境作用域链已被销毁,但活动变量还留在内存中,直至闭包销毁才会被销毁。
可将闭包设置为null以解除引用,释放内存。过度使用闭包会占用更多内存,所以避免使用闭包。
在这里插入图片描述

4.闭包只能获取闭包函数变量的最后一个值
如:

Function fx{
Var result=new Array();
for(var i=0;i<10;i++){
 result[i]=function(){
return i;
};
 return result;
}//result全为10
改进:
Function fx{
Var result=new Array();
for(var i=0;i<10;i++){
 result[i]=function(num){
function(){
return num;
}(i);
}
return result;
}

参数按值传递,将i值赋给num.
4.闭包中的this和arguments
每个函数在调用时都会自动获取两个变量:this和arguments.所以闭包搜索this和arguments时只会搜索到自身的活动变量,从中或这两个变量,不会访问外部函数中的这两个变量()因此若闭包为匿名函数则this为window.
可以将外部函数的this保存在一个闭包能访问到的变量里。
如下:

Var name=”my window”;
var o={
name:”jane”;
getname:function(){
return function(){
return this.name;};}
};
alert(o.getname);//my window
修改:
Var name=”my window”;
var o={
name:”jane”;
getname:function(){
var that=this;
return function(){
return that.name;};}
};
alert(o.getname);//my window

5.模仿块级作用域
js没有块级作用域,只有全局和函数作用域。
可以用匿名函数模仿块级作用域。
(function(){})()
等同于var var1=function(){};var1();(function(){})加括号是为了不被js当成函数声明。
把代码放进这个匿名函数里就可以用函数作用域模仿块级作用域。
初始化未经声明的变量,该变量为全局变量,但在严格模式下会出错。

六、BOM

1.窗口位置
获取浏览器窗口左边和上边的位置:左上角是圆点(0,0)
var leftpos=(typeof window.screenLeft==”number”)?window.sreenLeft:window.screenX;
var toppos=(typeof window.screenTop==”number”)?window.sreenTop:window.screenY;
移动窗口:window.moveTo(x,y)移动到点(x,y)window.moveBy(x,y):向左(负)/右(正)移动x,向上(负)/下(正)移动y.
但这两种方法在opera即ie7及更高版本被禁用。
2.浏览器窗口大小:outerWidth和outerHeight
视图区大小(减去边框):innnerWidth和innerHeight
在chorme中都是视图区大小
3.window.open(url,新窗口/”blank”)
window.location:获取url,location:hash,post,pathname,href,search,protocol
navigator.userAgent:用户代理检测
history.go(n):前进n页,history.go(-n):后退n页,history.go(url):跳转到最近的url
前进:history.foward(),后退:history.back()
浏览器内核:firefox:gecko,safari\chorme\ios\android:webkit

七.DOM(略)

1.js中的所有节点类型都继承自Node类型。方法:appendChild(),removeChild(),
replaceChild(),insertBefore()
2.Document类型表示整个文档,是根节点。document对象是Document类的一个实例
获取第一个节点:document.documentElement、childNodes[0]、firstChild
获取其他:document.body、document.doctype、document.URL, document.domain,
.anchors(获取所有带name的a标签),.form,.images,.links(获取所有带link的a标签)
getElementById(),getElementsByTagName(),getElementByName()
文档写入:document.write()/writeln()
3.Element类型
获取设置移除特性:getAttribute(),setAttribute(),removeAttribute(),
创建属性:
var div=document.createElement(“div”),document.body.appendChild(div)
querySlector(),querySlectorAll()

八、事件

1.事件流:从页面中接收对象的顺序
事件冒泡:从具体元素开始接收,逐级向上传递直到document对象(IE5.5及更早会跳过html元素,IE9,firefox,chorme和safari会冒泡到window对象)
事件捕获:从不具体节点到具体节点(IE不支持,不常用)
DOM事件流:事件捕获阶段,具体节点接收阶段,事件冒泡阶段
2.事件处理程序:var btn=document.getElementById(“btn”);
在这里插入图片描述

跨浏览器的事件处理程序

var EventUtil={
addHander:function(element(元素),type(事件),hander(处理程序)){
if(element.addEventListener){
element. addEventListener(type,hander,false)
}
else if(element.attachEvent){
element.attachEvent(“on”+type,hander);
}
else{ element[“on”+click]=hander;}
},
removeHander:function(){}
};
EventUtil.addHander(btn,”click”,hander)

3.事件对象event
DOM事件对象(DOM0和DOM1)
event传入事件处理程序中
btn.οnclick=function(event){}
btn.addEventListener(“click”,function(event){},false)
event的属性:
event.target:事件的目标
event.currentTarget:指向绑定事件处理程序的元素,值与this相等。
event.type:事件的类型
event的方法:
event.preventDefault():阻止默认行为
event.stopPropagation:阻止冒泡

九、AJAX与comet

ajax不用刷新页面就能从服务器获取数据,comet服务器向页面推送数据(服务器推送)
1.XMLHttpRequest对象
var xhr=new XMLHttpRequest();
XMLHttpRequest对象的方法:
创建请求:XMLHttpRequest.open(“get”/”post”,”url“,false/true)bool值表示是否异步。
发送请求:XMLHttpRequest.send(var):var为要发送的数据,若不需要发送数据则var=null.
2.同步
等服务器响应请求后才会继续执行,收到响应后会自动填充xhr对象的属性:
responseText:服务器返回的文本
responseXML:响应数据的XML DOM数据
status:响应的http状态
statusText:http状态的说明
status:200表示成功,304表示请求资源没有被更改,可以使用浏览器中缓存的版本。
var xhr=new XMLHttpRequest();
xhr.open(“get”,”example.txt”,false);
xhr.send(null);
if((xhr.status>=200&&xhr.status<300)||xhr.status==304){
alert(xhr.responseText);
}
else{alert(“wrong”+xhr.status);}

3.异步
不必等待响应
readyState属性表示请求/响应过程的活动状态:
0:未初始化,尚未调用open()
1:启动。已open()未send()
2:发送。已send()未接受响应
3:接收。已接受到部分响应
4:完成。接收到全部响应。
readyState变化会触发readystatechange事件,在open之前为xhr绑定此事件

xhr.onreadystatechange=function(){
if(xhr.readystate==4){
if((xhr.status>=200&&xhr.status<300)||xhr.status==304){
alert(xhr.responseText);
}
else{alert(“wrong”+xhr.status);}
}
};
xhr.open(“get”,”example.txt”,false);
xhr.send(null);

4.get,post请求
post作为请求主题提交,可以包含很多数据且格式不限
get查询字符串每个参数:名=值
5.跨域资源共享(cors)
xhr实现ajax通信,有跨域限制,xhr对象是能访问同端口、同协议、同域名的资源。
cors可以实现跨域:使用自定义的http头部让浏览器与服务器通信。
IE实现cors:引入XDR对象
var xdr=new XdomianRequest()与xhr类似,不同的是它只有两个参数(get/post,url)只支持异步。
其他浏览器实现cors:使用标准xhr对象并在open中传入绝对url即可.
6.JSONP跨域
格式包含在回调函数中的json:callback{{“name”:”jane”}};
包含两部分:回调函数和数据
回调函数在url中指定,数据是传入回调函数的json数据
如:https://free.net/json/?callback=handleresponse
因为<script>不受跨域影响,所以可以为script.src指定一个跨域url
7.comet
两种实现方法:1)长轮询:页面向服务器发送请求,服务器保持连接打开,直到有数据可发送,发送完后浏览器关闭连接,随即又发送新请求。
2)http流:浏览器向服务器发送一个请求,服务器保持连接打开,周期性地向浏览器发送数据。
通过监听readystatechange事件,readystate为3时,分割reponseText以获取最新数据,通过progress回调函数处理传入的新数据,当readyState为4时,执行finished回调函数传入响应的全部内容。
7.Web Socket API
实现全双工,双向通信
使用自定义的模式ws://(而不是http), wss://(而不是https)
var socket=new Web Socket(“ws://www.example.com/”)
传入绝对url,支持跨域
readyState:
0:正在建立连接
1:已经建立连接 socket.open()
2:正在关闭连接
3:已经关闭连接 socket.close()
发送数据:socket.send()

8.CRSF(跨站点请求伪造)
未授权系统伪造自己使之有权访问某个资源,窃取数据或销毁数据
预防:每次请求都要附带经过相应算法计算得到的验证码

十、高级技巧

1.函数绑定
bind可以将函数绑定到指定的环境,bind接收一个函数和一个环境,返回一个在给定环境中调用给定函数的函数,并原封不动的传递所有参数

function bind(fn,context){
return fn.call(context,arguments);
}

2.函数柯里化
将返回的函数参数进行排序
第一个参数是要可里化的函数,其他参数是要传入的值。用slice(arguments,1)取得外部函数除第一个参数外(第一个参数是外部函数名)的所有参数,用slice(arguments)获取内部函数所有参数,用concat将参数组合,最后将结果传给该函数。

function curry(fn){
var args=Array.prototype.slice.call(arguments,1);
return function(){
var innerargs= Array.prototype.slice.call(arguments);
var fianlargs=args.concat(innerargs);
return fn.call(null,finalargs);
};
}
function add(num1,num2){
return num1+num2;}
var cur=curry(add,1);
alert(cur(3));//4

与绑定函数结合:在任意环境以任意参数执行任意函数

function bind(fn,context){
var args=Array.prototype.slice.call(arguments,2);//除了fn和context
return function(){
var innerargs= Array.prototype.slice.call(arguments);
var fianlargs=args.concat(innerargs);
return fn.call(context,finalargs);
}

3.定时器
定时器的事件间隔是指何时将定时器的代码放入等待队列中。
函数节流:某些代码不可以没有间断的执行
function throttle(method,context){//参数为要执行的啊含糊和作用域
clearTimeout(method.tId);//先清楚之前的定时器
method.tId=setTimeout(function(){//新建一个定时器
method.call(context);},100);//定时器在当前环境执行
定时器ID存储于tId

十一、客户端存储

1.离线检测:nevigator.onLine属性
方法:nevigator.online:离线变在线时触发
nevigator.offline:在线变离线时触发
2.cookie,大小在4095b以内
3.web存储机制:sessionStorage和globalStorage(h5中用localStorage代替)
1)sessionStorage是storage的实例
用来存储某个会话的数据,暂时的,浏览器关闭即消失
使用方法存储数据:sessionStorage.setItem(“name”,”jane”)
使用属性存储数据:sessionStorage.name=“jane”
使用方法获取数据:sessionStorage.getItem(“name”,”jane”)
使用属性获取数据:var name=sessionStorage.name
2)globalStorage,跨越会话存储数据,所以要指定在哪个域可以访问数据。
globalStorage[“域名”]:才是是storage的实例
使用方法存储数据:globalStorage[“域名”].setItem(“name”,”jane”)
使用属性存储数据:globalStorage[“域名”].name=“jane”
使用方法获取数据:globalStorage[“域名”].getItem(“name”,”jane”)
使用属性获取数据:var name= globalStorage[“域名”].name
3)localStorage:访问时,页面必须要同协议,同域名,同端口
使用方法存储数据:localStorage.setItem(“name”,”jane”)
使用属性存储数据:localStorage.name=“jane”
使用方法获取数据:localStorage.getItem(“name”,”jane”)
使用属性获取数据:var name=localStorage.name

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值