3-1a.第一部分
1.null和undefined的区别?
undefined表示变量声明但未初始化值,null用来保存对象,表示一个空对象。
任何时候都不建议设置一个变量为undefined,但是如果保存没有真正对象的变量,应该设置成null。
alert(null==undefined); // true
2.Js原型,原型链是什么,特点?
每个对象都有一个内部属性 prototype,但是对象实例不具有该属性,我们通常称之为原型。原型的值可以是一个对象,
也可以是null。如果它的值是一个对象,则这个对象也一定有自己的原型。这样就形成了一条线性的链,我们称之为原型
链。但是对象实例不具有prototype属性,只有一个内部的不可访问的__proto__属性。__proto__是对象中一个指向
相关原型的神秘链接。
每个对象都会在其内部有一个属性,就是prototype(原型),当我们访问一个对象的属性时,如果这个对象内部不存在
这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,于是就这样一直找下
去,也就是我们平时所说的原型链的概念。
关系:instance.constructor.prototype = instance.__proto__
特点:
JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型
时,与之相关的对象也会继承这一改变。通过原型可以实现对象的属性继承!!!
对象,函数对象,原型对象:
1. 所有的对象都有__proto__属性,函数被用作构造函数来创建实例时,该属性指向该对象的原型.
2. 所有的函数对象都有prototype属性,该属性的值会被赋值给该函数创建的实例对象的_proto_属性.
3. 所有的原型对象都有constructor属性,该属性指向该原型的实例的构造函数.
4. 函数对象和原型对象通过prototype和constructor属性进行相互关联.
3.ajax
ajax缓存是根据url地址来缓存的,换句话说,同样的一个url地址只缓存一次。实际应用中到底
要不要和多久一次清一下缓存,是由架构师说了算。
ajax使用:
a.请求并显示静态文本文件。
b.获取动态数据文件:请求js文件(放json数据的文件)
eval使用:1、计算字符串里面的值。2.eval(它里面可以放任何一段js代码,并运行)
c.局部刷新:请求并显示部分网页文件。
for(i=0;i<aBtn.length;i++){
aBtn[i].index = i;
aBtn[i].onclick = function(){
ajax("page"+(aBtn[i].index+1)+".txt",function(str){
var aData = eval(str);
oUl.innerHTML = '';
for(i=0;i<aData.length;i++){
var oLi = document.createElement('li');
oLi.innerHTML = '<strong>'+aData[i].user+'</strong><i>'+aData[i].pass+'</i>';
oUl.appendChild(oLi);
}
});
}
}
ajax原理:
http请求方法:
get:更适合获取数据,如浏览帖子;
post:更适合上传数据,如用户注册
get,post区别:
get把数据放在url里面,安全性低(在浏览器里鼠标悬浮历史浏览链接,浏览器下方会出现数据信息),容量小;优点便于分享,会缓存。
post把数据放在http content里面,安全性一般,容量几乎无限
ajax请求编写:
1.创建ajax对象;2.连接服务器;3.发送请求;4.接收返回
js有个特性:alert(a)用一个不存在的变量会报错;alert(window.a); 用一个不存在的属性 只会undefined
2.请求状态监控,onreadystatechange事件
-readyState属性:请求状态
0:未初始化,还未调用open方法;
1:调用send方法,正在发送请求;
2:send方法完成,已收到全部响应内容;
3:正在解析响应内容;
4:响应内容解析完毕,等待客户端调用
-status属性:请求结果
-responseText
function ajax(url,fnSucc,fnFail){
var oAjax = null;
if(window.XMLHttpRequest){
oAjax = new XMLHttpRequest();
}else{
oAjax = new ActiveXObject('Microsoft.XMLHTTP');//iE6及以下依赖
插件
}
oAjax.open("GET",url,true);//工作在异步下
oAjax.send();
oAjax.onreadystatechange = function(){
if(oAjax.readyState==4){
if(oAjax.status==200){
fnSucc(oAjax.responseText);
}else{
if(fnFail){
fnFail();
}
}
}
}
}
主要:XML现在已淘汰,相对于json太臃肿了.还有所有字符集要求一样。
4.js跨域问题
同源策略:同源指的是主机名、协议和端口号的都相同(哪怕不同域名指向同一个ip都不行)
解决方案:
*a.script标签:
script标签引用的文件要求返回的值,务必是var json={"Name":"zhangsan"},或
json({"Name":"zhangsan"})。
就是以jsonp形式,建立个json函数,然后传参过去调回json格式数据。
jsonp:json + padding(内填充的盒子):box(包裹着json格式的数据),那么在父域下面就可以写个同名函数,
以子域的传来的数据作为参数。
(一)
<script>
function 包裹着json格式的数据的同名函数(jsondata){
//处理json数据
}
</script>
<script src="子域链接?子域那边规定的格式参数名=上面定义的包裹着json格式的数据的同名函数"></script>
主要:获取数据的地址后面还有一个callback参数,按惯例是用这个参数名,但是得按照提供数据的那一方
的规定格式用参数名。
这样jsonp的原理就很清楚了,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中
指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。
<script type="text/javascript">
var result = null;
function callback(data) {
result = data;
}
window.onload = function () {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://example.com/data.php?callback=callback";
var head = document.getElementsByTagName("head")[0];
head.insertBefore(script, head.firstChild);
};
</script>
如果你的页面使用jquery,那么通过它封装的方法就能很方便的来进行jsonp操作了。
(二)
<script>
$.getJSON('http://example.com/data.php?callback=?',function(jsondata){
//处理json数据
});
</script>
原理是一样的,只不过我们不需要手动的插入script标签以及定义回掉函数。jquery会自动生成一个全局函数来
替换callback=?中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用。$.getJSON
方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用
jsonp的回调函数。
(三)
$.ajax({
dataType: 'jsonp',
//jsonp的值自定义
jsonp: 'jsoncallback',
//返回Json类型
contentType: "application/json;utf-8",
});
*b.location.hash + iframe
原理是利用location.hash来进行传值。
假设域名a.com下的文件cs1.html要和cnblogs.com域名下的cs2.html传递信息。
1) cs1.html首先创建自动创建一个隐藏的iframe,iframe的src指向cnblogs.com域名下的cs2.html页面
2) cs2.html响应请求后再将通过修改cs1.html的hash值来传递数据
3) 同时在cs1.html上加一个定时器,隔一段时间来判断location.hash的值有没有变化,一旦有变化则获取
获取hash值
注:由于两个页面不在同一个域下IE、Chrome不允许修改parent.location.hash的值,所以要借助于
a.com域名下的一个代理iframe
代码如下:
先是a.com下的文件cs1.html文件:
function startRequest(){
var ifr = document.createElement('iframe');
ifr.style.display = 'none';
ifr.src = 'http://www.cnblogs.com/lab/cscript/cs2.html#paramdo';
document.body.appendChild(ifr);
}
function checkHash() {
try {
var data = location.hash ? location.hash.substring(1) : '';
if (console.log) {
console.log('Now the data is '+data);
}
} catch(e) {};
}
setInterval(checkHash, 2000);
cnblogs.com域名下的cs2.html:
//模拟一个简单的参数处理操作
switch(location.hash){
case '#paramdo':
callBack();
break;
case '#paramset':
//do something……
break;
}
function callBack(){
try {
parent.location.hash = 'somedata';
} catch (e) {
// ie、chrome的安全机制无法修改parent.location.hash,
// 所以要利用一个中间的cnblogs域下的代理iframe
var ifrproxy = document.createElement('iframe');
ifrproxy.style.display = 'none';
ifrproxy.src = 'http://a.com/test/cscript/cs3.html#somedata'; // 注意该文件在"a.com"域下
document.body.appendChild(ifrproxy);
}
}
那么a.com下的域名cs3.html
//因为parent.parent和自身属于同一个域,所以可以改变其location.hash的值
parent.parent.location.hash = self.location.hash.substring(1);
*c.window.name + iframe
window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都
是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口
载入过的所有页面中的,并不会因新页面的载入而进行重置。
在www.a.com/a.html中:
<script>
window.name="jwjwj";
setTimeout(function(){
//3秒后载入新的页面到当前窗口
window.location="http://www.script.a.com/b.html";
},3000)
</script>
在www.script.a.com/b.html中:
<script>
alert(window.name);
</script>
d.document.domain + iframe
只有在主域相同的时候才能使用该方法。document.domain的设置是有限制的,我们只能把document.domain
设置成自身或更高一级的父域,且主域必须相同。例如:a.b.example.com 中某个文档的document.domain
可以设成a.b.example.com、b.example.com 、example.com中的任意一个。
在www.a.com/a.html中:
<script>
document.domain='a.com';
function onLoad(){
var oIframe=document.getElementById('frame');
//获取iframe里面的window对象
var win= oIframe.contentWindow;
//获取window里面的document对象
var doc=win.document;
//获取window里面的name属性
var name=win.name;
}
</script>
<iframe src="http://www.script.a.com/b.html" id="frame" onload="onLoad()"></iframe>
在www.script.a.com/b.html中:
document.domain = 'a.com';
这样我们就可以通过js访问到iframe中的各种属性和对象了。
不过如果你想在http://www.a.com/a.html页面中通过ajax直接请求http://www.script.a.com/b.html
页面,即使你设置了相同的document.domain也还是不行的,所以修改document.domain的方法只适用于不同
子域的框架间的交互。如果你想通过ajax的方法去与不同子域的页面交互,除了使用jsonp的方法外,还可以用
一个隐藏的iframe来做一个代理。原理就是让这个iframe载入一个与你想要通过ajax获取数据的目标页面处在
相同的域的页面,所以这个iframe中的页面是可以正常使用ajax去获取你要的数据的,然后就是通过我们刚刚讲
得修改document.domain的方法,让我们能通过js完全控制这个iframe,这样我们就可以让iframe去发送
ajax请求,然后收到的数据我们也可以获得了。
使用document.domain+iframe跨域实例
首先我们假设主页面地址为:http://www.js8.in/mywork/crossdomain/index.html,我们要加载的内容
是位于work.2fool.cn域名下的helloworld.txt。我们需要在主页面中设置document.domain为2fool.cn,
然后主页面添加一个iframe,src为域名work.2fool.cn下的一个url,在iframe页面中同样设置
document.domain为2fool.cn,同时iframe中需要添加Ajax的函数,例如引入jQuery.js。
主页index.html的主要代码如下:
<button onclick="crossDomain();">开始跨域</button>
<div id="ajax"></div>
<iframe src="http://work.2fool.cn/crossdomain/iframe.html" id="iframe" style="display:none;"> </iframe>
<script type="text/javascript">
document.domain = '2fool.cn';
function crossDomain(){
var iframe=document.getElementById('iframe').contentWindow.$;
iframe.get("http://work.2fool.cn/crossdomain/helloworld.txt",function(data){
document.getElementById("ajax").innerHTML=data;
});
}
</script>
iframe页面主要代码如下:
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript"> document.domain = '2fool.cn'; </script>
e.html5 postMessage
参考:http://www.cnblogs.com/2050/p/3191744.html
f.flash
g.服务器代理:服务器来做的,XMLHttpRequest的代理文件
5.清除浏览器缓存(?)
浏览器缓存的意义在于提高了执行效率,但是也随之而来带来了一些问题,导致服务端修改了js、css,客户端不能
更新
方法一 生成随机数字
代码如下:
<script type=”text/javascript“ src=”/js/test.js?+Math.random()+“></script>
缺点,浏览器缓存失去意义,每次都动态加载。
方法二 版本号控制,设置全局变量,每次发布前版本号加1
代码如下:
<script type=”text/javascript“ src=”/js/test.js?v=<%=v%>“></script>
推荐这种做法,这种做法比较简单。缺点是HTML页面不能使用,但是这种页面应该不太多
6.事件
document本质:
document.childNodes[0].tagName ==> !是文档头声明节点
document.childNodes[1].tagName ==> HTML节点
所以document是html和文档头声明的虚拟的父节点。
事件:用来获取事件相关详细信息,如鼠标位置,键盘按键。
事件流:
事件冒泡:由具体对象开始接收,
如自定下拉菜单需要取消冒泡:oEvent.cancelBubble=true;
document.onmousemove:无论鼠标在document上什么地方移动,事件都发生。
实例:1.跟随鼠标移动的提示框;2.一连串的div跟着鼠标(逆序for循环,最后一个跟着前
一个div的坐标移动,第一个跟着鼠标移动)
鼠标事件:
onclick=onmousedown+onmouseup
键盘事件:
onpress=onkeydown+onkeyup;左键oEvent.keyCode:37,右键:39,回车:13,
ctrlKey,altKey,shiftKey
实例:1.回车或者ctrl和回车提交留言(oEvent.ctrlKey && oEvent.keyCode==13)
offsetWidth和offsetLeft都是实际宽和左边距离,offsetWidth=width+padding+border;
offsetLeft=left+margin;
默认行为/事件:
浏览器自身自带的一些功能。
如何阻止默认行为?return false;实例1:document.oncontextmenu:弹出右键菜单事件
,阻止浏览器默认菜单;实例2:只能输入数字的文本框,onkeydown,keyCode(0-9 49-57
退格 8)return false
拖拽:
onmousedown:存储距离,disX=oEvent.clientX-oDiv.offsetLeft;
onmousemove:根据距离计算div最新的位置=oEvent.clientX-disX;这个事件不会根据鼠标
有没有按下去才发生,只要移动就发生。所以拖拽需要做到在鼠标按下之前,不要发生跟随鼠标
移动(放在onmousedown事件里面)。
onmouseup:清理事件(也放在onmousedown事件里面,onmousemove=null让鼠标松开的时
候,move不在发生,onmouseup=null不必要事件浪费。)
注意:
1.onmousemove和onmouseup事件的加在document上,否则,鼠标移动过快,就会出div
,拖拽就会停下来,而document在页面里面无限大。
2.在低版本的FF下,空的div拖拽bug,鼠标样式会变成紧致样式(阻止默认事件:onmousedown
下return false)
3.防止拖到外面:
if(oEvent.clientX-disX < 0){
oEvent.clientX-disX = 0;
}
if(oEvent.clientX-disX > document.documentElement.clientWidth){
oEvent.clientX-disX = document.documentElement.clientWidth;
}
7.cookie
作用:给网站保存一些信息在客户端,比如自动登录,记住用户名。
和缓存的区别:缓存是那些访问的页面,html,css,js,图片等文件。并且缓存不受js控制,但可以
清理缓存,大部分是通过服务器和客户端设置来控制缓存。 而cookie是完全由js控制的。
特性:同一网站的所有网页共享一套cookie;数量一般不超过50个,大小以k为单位,数量,大小有限
,现在一般不纯粹使用cookie,多种cookie结合使用;有过期时间;ajax必须运行在服务器环境下,
cookie也是,但是只想在本地测试,特别点是可以在火狐下。
cookie使用:
1.设置
如果没有设置过期时间,cookie在窗口关闭后就清除,且不会覆盖。
var oDate = new Date();
oDate.setDate(oDate.getDate()+30);
document.cookie="color=blue";
document.cookie="username=wj;expires=" + oDate;
console.log(document.cookie);//color=blue;username=wj
封装cookie:
function setCookie(name,value,iDate){
var oDate = new Date();
oDate.setDate(oDate.getDate()+30);
document.cookie = name+'='+value+';expires='+iDate;
}
2.获取
function getCookie(name){
var arr = document.cookie.split(';');
var i=0;
for(i=0;i<arr.length;i++){
var arr2 = arr[i].split('=');
if(arr2[0] == name){
return arr2[1];
}
}
return '';
}
3.删除
function removeCookie(name){
setCookie(name,'1',-1);
}
4.实例:
a.用cookie记录上一次关闭窗口前的div的位置
onmouseup:setCookie('x',oDiv.offsetLeft,5);
window.onload 后 var x = getCookie('x');if(x){oDiv.style.left = x + 'px';}
b.用cookie记录上次登录的用户名
点击提交的时候:
oForm.onSubmit = function(){
setCookie('user',oUser.value,5);
}
oUser.getCookie('user');
obnClear.onclick = function(){
removeCookie('user');
oUser.value = '';
}
8.面向对象
什么是对象?对象是一个整体,对外提供一些操作。
什么是面向对象?比如jquery,使用对象的时候,只关注对象提供的功能,不关注其内部实现
细节。
js中的面向对象:
面向对象编程(opp)特点:
抽象:抓住核心问题;封装:不考虑内部实现,只关注功能使用;继承:从已有对象基
础上,继承出新的对象(多重继承:多个父级,多态:父类和子类有相同的操作,但这
些操作又有些不一样);
对象组成:方法和属性(和函数,变量区别,变量没有所属关系,自由自在);
this定义:arr.show=function(){this}; oBtn.onclick=function(){this};
this指的是当前方法属于谁,除了在this那个函数前面放一个new才失效。例如 function show(){this} show()//this:window;
因为全局的变量和函数属于window对象;
创建对象:
1.工厂模式:原料,加工,出厂
缺点:
1.没有new,new的话,构造函数里面有些东西可以简化;
2.每个对象实例都有自己的函数,浪费资源,因为没一个function就会new Fuction()
对象;
//构造函数
function createPer(name,sex){
var obj = new Object();
obj.name = name;
obj.sex = sex;
obj.showMess = function(){
alert(this.name+"/"+this.sex);
}
return obj;
}
var p1 = createPer('wj','女');
var p2 = createPer('wj2','男');
p1.showMess();