本书的JSjavascript
1.1 执行js代码html
javascript:alert(‘执行js’);//通常放在超连接中,用户点击即执行,
<script>alert("执行js")</script>前端
1.2 变量赋值java
var a = 1;//显式 a =1; //隐式
1.3 全局变量与局部变量node
... var scope = "全局变量"; function test(){ alert(scope); // undefiend var scope = "局部变量"; alert(scope); // 局部变量 }
由于全局变量被局部变量覆盖了.虽然局部变量的scope还没赋值,可是已经在方法里”占”上位置了.
但若是把局部变量的var删了,就会先输出全局变量后输出局部变量,由于没有var在方法里给局部变量”占”位置;git
1.4 浮点数github
var a =.333 var b = a * 5; alert(b);
得出的结果是 1.66499999999999999
因此在js中判断浮点数是否相等 建议判断二者的差值是否小于一个足够的数(例如0.0000000000001)web
1.5 字符串正则表达式
js中没有字符类型变量 “”与’‘一致编程
var s ="abcdefg" //b = "def" b = s.slice(3, -1);
1.6 字符串的正则表达式方法中
1.7 undefined和null
null == undefined //true null === undefined //false
undefined 是没设值
null则是设定了为null值
1.8 运算符
//逗号运算符 取最右返回值 a = (b =5 , c = 7 , d =56) //a =56 a = void(b =5 , c = 7 , d =56) //a = undefined
1.9 typeof和instanceof
typeof 用来得到 实例类型 :
typeof("123"); //string
instanceof 判断变量是否为某类的实例
var a = [4,5]; alert(a instanceof Array); //true
1.10 语句
抛出异常
throw new Error("用户自定义异常"); //通常用于终止程序和返回错误提示是个不错的选择; try{ }catch(e){ alert(e.message); // "用户自定义异常" }
for in
//这回输出浏览器的全部属性,作浏览器兼容以前能够考虑看看. for( prop_name in navigator){ document.wrti(prop_name + " : " + navigator[propname]); }
跳出命名for
outer: for(...){ for(...){ ... continue outer; } }
1.11 函数
js 容许先调用函数 再定义函数
1.11.1 定义匿名函数
var show_name = function(name){ alert(name); } show_name("K"); //K
这样的好处是什么,若是直接定义function 它实际上也是建立了一个对象
1.11.2 函数既对象
var hello = function(){...}; hello instanceof Function //true; hello instanceof Object //true; alert(heelo) //输出函数源代码
1.11.3 调用函数方式的不一样
1.11.4 this关键字.
var hello =function(){...} window.hello(); var p = { wark: function(){...} } p.wark();
1.11.5 函数中的变量有三种
function Person(){ //局部变量 只能在函数里访问 var id ; //实例属性 经过对象.访问 this.age ; //类属性 经过Patient.name访问 与static相似 Person.name ; }
1.11.6 js是一种动态语言,能随时给对象增长属性和方法
function Student(){ }; var student =new Student(); //动态增长name属性 student.name = 'K'; alert(sutdent.name) //K Student.age =22 ; alert(Student.age); //22 类属性也是能够动态添加的
1.11.7 调用函数的三种方式
windows.alert(); //or alert();
var each = function(array,fn){ for(var index in arrary){ //null表示以window为调用者fn函数 fn.call(null,index,arrary[index]); } } each([4,20,3] , function(index ,ele){ alert("第 " + index "个元素是 : " + ele); });
call()调用函数语法为:函数引用.call(调用者,参数1,参数2...)
直接调用函数语法为:调用者.函数(参数1,参数2 ...) = 函数.call(调用者,参数1,参数2 ...)
apply()调用
apply和()call()基本类似,区别以下:
经过call()调用函数时,括号必须详细列出每一个参数
经过apply()动态地调用函数时,能够在括号中以arguments来表明全部参数
var myfun = function (a , b){ alert(a + " " +b); } myfun.call(window ,12 ,23); //12 23; myfun.apply(window ,[20 , 39]); //20 39 var example = function (num1 ,num2){ //直接调用arguments表明调用者(example,this表明example)时的传入的全部参数 myfun.apply(this,arguments); } example(20,40) //20 40
1.11.8 函数的独立性
在函数A中能够定义函数B,可是函数B仍是独立于函数A
function Person(name){ this.name = name; this.info = function(){ alert(this.name); } } var person =new Person('K'); person.info(); //K var name = 'K_window'; //因为window为调用者 ,this.name访问的是window.name p.info.call(window); //K_window
来爽一发猫学狗叫?.
function Dog(name,bark){ this.name = name; this.bark = bark; this.info =function(){ alert(this.name + " " + this.bark); } } function Cat(name){ this.name =name; } var dog = new Dog("K","汪汪!"); var cat = new Cat("K_2"); dog.info.call(cat); //K_2 undefined
1.11.9 参数传递方式
和JAVA同样 都是值传递拉~.
基本类型
function change(arg){ arg =10 ; alert(arg); } var x = 5; alert(x); //5 change(x); //10 alert(x); //5
复合类型
function change(person){ person.age = 10; alert(person.age); person = null; } var person = {age : 5}; alert(person.age); //5 change(person); //10 alert(person.age); // 10 alert(person); // []object Object]
复合类型的传递为值传递,原person和参数person指向同一javascript对象,因此当改变age的时候,是在改变javascript对象的age,可是参数person赋值为null,原person并没有改变.
1.11.10 空参数
function text(person){ alert( typeof parson); } text(); //undefined
因此对于弱类型,方法重载是无做用的,由于js会把空参数当作undefined传递进去;
同名函数,后面出现的会覆盖前面的,不管参数个数是多少.
1.11.11 对象和关联数组
javascript和Map有点相似,当key为对象,value为函数,该该函数就是对象的方法,当key为对象,value为基本类型,则该基本类型为对象的属性.(以上为便于理解,切勿细琢)因此访问属性时,能够obj.propName也能够obj[propName].
但有时候咱们只能用obj[propName],由于.propName不能把propName当作变量处理,而是把他当成’propName’字符串
function Person(name){ this.name =name; this.info = function(){ alert(K); } } var person = new Person("K"); //遍历person属性 for (propName in person){ alert(p[propName]);//alet K info源代码 假如此处用p.propName则undefined,由于Person无'propName'变量. }
1.11.12 继承和prototype
在一个类(函数)中定义一个函数会致使
function Person(){ var local = "局部变量" this.info = function(){ //产生闭包 alert(local); } } var person = new Person(); person.ifno(); // 局部变量
解决方案:prototype
增长了prototype属性的类可视为继承了原先的类(伪继承)
function Person(){...} var person = new Person(); //person.wark(); 程序报错wark不存在 Person.prototype.wark = function(){...} person.wark(); //ok
在prototype以前实例化的类会具备wark方法吗? 有的,由于prototype这样并不会产生一个新的类,而是直接动态的往Person里加函数.
判断某方法是否继承了该对象
该对象.prototype['某方法'] != undefined; var test = new 该对象(); test.某方法 !=undefined ;
1.12 建立对象三种方式
//(单身汪别说我不教你)
function Person(name){...} var person_1 = new Person(); var person_2 = new Person('K'); //js不存在方法重载,空参数undefined顶替
var my_obj = new Object(); my_ojb.name = 'K'; my_obj.handsome = function(){...} function text(){...} my_obj.text = text;//不要添加(),否则会认为是调用方法
ver person = { name : 'K', school : ['ChangAn','TianJin'], girl_friends :[ { name : 'Haski', age : 11 }, { name : 'Samoyed', age : '8' } ] } alert(person.girl_friends[0].name); //Haski
DOM操做其实JQuery已经作得很好了,这里简单补充一下原生JS的知识
HTML文档中只有一个根节点
2.1 访问HTML元素
Node parentNode: 返回父节点 Node previousSibling: 返回前一个兄弟节点 Node nextSibling: 饭后后一个兄弟节点 Node[] childNodes 返回当前节点的全部节点 Node[] getElementsByTagName('标签名称'): 返回当前节点具备制定标签的子节点 //注意ol标签的子标签IE8和其余浏览器不同(其余浏览器会把ol下的li和其后面的空白分别当成2个节点,IE8则不会)
2.2 增长HTML函数
2.3 添加节点
2.4 删除节点
2.5 window对象
for(var propName in window.screen){ alert(propName+":" +screent[propname]); }
var timer; var cur = new Date().getTime(); var setTime = function(){ document.getElementById("tm").innerHTML = new Date().toLocationString(); if(new Date().getTime- cur > 60 *1000){ clearInterval(timer); } } //每1S执行一次,执行了60次就暂停 timer = window.setInterval("setTime()",1000);
2.6 navigator和地理位置
navigator汉堡浏览器全部信息,遍历循环获取信息
for(var propName in window.navigator){ alert(propName + ":" + window.navigator[propName]); }
HTML5新增geolocation属性
Geolocation提供的方法
上面的前两个方法的options参数是一个对象,可包含3个变量
var geoHandler = function(position){ var geoMsg = "用户地址位置是 : <br/>" geoMsg += "timestamp属性为 :" + position.timestamp + "<br/>"//获取位置的时间 var cords =position.coords; for(var prop in coords ){ geoMsg += prop + ": " + coords[prop] +"<br/>"//经纬度,移动速度等 } document.writeln(geoMsg); } var errorHandler = function(error){ var errMsg = { 1: '用户拒绝了位置服务' 2: '没法获取地址位置信息' 3: '获取地理位置信息超时' }; alert(error[error.code]); } navigator.geolocation.getCurrentPosition(geoHandler , errorHandler , { enableHighAccuracy:true, maximuAge:1000 });
2.7 HTML5新增浏览器分析
实现该功能主要经过performance对象
其中的(PerformanceTiming)timing属性包含加载时间相关的属性
另外(PerformanceNavigation)navigation,主要属性有
type :
TYPE_NAVIGATE(数值为0): 超连接/输入url TYPE_RELOAD(1): 从新加载方式,diaoyonglocation.reload()等 TYPE_BACK_FORWARD(2): 经过浏览器的前进方式 TYPE_RESERVED(255): 未知方式
3 事件处理机制
3.1 常见事件
3.2 事件处理和this
p.info = function(){ alert(this.name); } document.getElementById("bt").onclick = p.info//this指向'bt'控件 document.getElementById("bt").onclick = new function (){ p.info();} //this老是指向p
注意表单设置id为x和name为y时候,至关于表单建立了x属性和y属性,因此id和name不能是关键字submit等
3.3 DOM
建立监听事件
objectTarget.addEventListener(“eventType”,handler,capture),第一个参数表示绑定的事件,如click、keypress之类的,第二个制定绑定的函数,第3个位boolean,true表示监听捕获阶段,false表示监听冒泡阶段
objectTarget.removeEventListener(“eventType”,handler,captureFlag): 删除绑定事件
捕获状态阶段的绑定事件先执行,事件冒泡状态阶段的绑定事件后执行. 捕获状态阶段从外往内触发,事件冒泡状态阶段从内往外触发.
绑定例子
var got_click = function (event){ for ( event_one in event){ alert(event_one + " : " + event[event_one]); } } document.getElementByID("test").addEventListener("cilck",got_click,true);
阻止事件传播
event.stopPropagation();
取消事件的默认行为,如跳转页面等,但不会阻止事件传播.
event.preventDefault();
3.3.1转发事件
DOM提供了dispathEvent方法用于事件转发,该方法属于Node
target.dispathEvent(Event event),将event转发到target上
DOM的dispath()必须转发人工合成的Event事件
document.createEvent(String type),tpy参数用于指定事件类型,eg:普通事件Events,UI事件UIEvents,鼠标事件:MouseEvents
初始化事件
initEvent(具体参数...) initUIEvent(具体参数...) intMouseEvent(具体参数...) //例子 <input id="bt1"> <input id="bt2"> ... var rd =function(evt){ alert("事件冒泡阶段: " + evt.currentTarget.value +"被点击了"); var e =document.createEvent("Evnets"); e.initEvent("click",true,false);//true表示是否支持冒泡,false表示是否有默认行为 document.getElementById("bn2").dispathEvent(e); } var go_click = function (evt){ alert("事件冒泡阶段: " + evt.currentTarget.value); } document.getElementById("bn1").addEventListener("click",rd,false); document.getElementById("bn2").addEventListener("click",go_click,false);; //点解按钮一结果 alert(事件冒泡阶段: 按钮一被点击了); alert(事件冒泡阶段:按钮2);
点击按钮1,按钮执行了前面按钮一被点击了提示语句后,将点击事件转给了按钮2,按钮2执行自身的点击事件.
4.1 Web Storage
使用理由之一Cookie的局限性:
Cookie大小被限制为4KB
Cookie会包含在每次HTTP请求中
Cookie网络传输未加密(除非整个应用都使用SSL)
Web Storage分两种
Session Storage: 生命周期与用户Session一致(用户Session是指:用户从访问网址到离开网址/关闭浏览器)
Local Storage: 保存在用户的磁盘中,失效的方式为用户/程序显示删除.
Web Storage的方法有
length: 返回key-value对数
key(index): 返回第index个key
getItem(key): 获取key对应的value
set(key,value): 设置key-value
removeItem(key): 删除key-value
clear(): 清除全部key-value
Web Storage包含在window对象中
当value为对象时,建议用JSON存储
4.2 构建离线应用
//代表该页使用index.manifest文件 <html manifest="index.manifest">
CACHE MANIFEST //第一行必须为上述字符 //指定版本号 #version 1 //本地缓存资源 CACHE inedx.html logo.jpg //不缓存的资源 NETWORK * //前者表示在线状态使用的资源,后者表明离线状态使用的资源 FALLBACK test.js offline.js
<!--conf的web.xml根元素中增长MIME映射--> <mine-mapping> <extension>manifest</extension> <mine-type>text/cache-mainfest</mime-type> </mime-mapping>
启动应用后,页面可刷新(即便离线状态),并使用离线时候的资源
4.2.1 判断在线状态
navigator.onLine属性: true表示在线
online/offline事件: 当在线/离线状态切换时,body上的online/offine事件会被触发,沿着document.body、document和window冒泡
window.addEventListener("offline",function(){ alert("离线状态") },true); if(navigator.onLine){ alert("在线"); }
4.2.2 applicationCache对象
js可经过applicationCache控制离线缓存.
status属性:
经常使用方法
setInterval(function(){ applicationCache.update() },2000); applicationCache.onupdateready = function(){ if(confirm("已从远程服务器下载了须要的缓存,是否更新?")){ applicationCache.swapCache(); location.reload(); } }
4.2.3 离线应用的事件与监听
访问html页面过程
当用户再访问index.html时,前面1~5彻底相同,接下来检测mainfest文件是否有改变.
worker中没法使用DOM、alert等与界面有关的操做.
使用理由:防止js阻塞主线程的js运行
WorkerAPI
onmessage =function(event){ var data =JSON.parse(event.data); var start =data.start; var end =data.end; var result =""; search: for (var n =start; n <= end :n++){ if(n%i==0){ continue search; } result +=(n+","); } } postMessage(result);
网页代码
<input name="start" ...> <input name="end" ...> <input type=button inclick="cal();" ...> ... var car =function(){ var start = parseInt(document.getElementById("start").value); var end = parseInt(document.getElementById("end").value); //建立线程 var cal = new Worker("worker.js"); var data ={ "start" : srart, "end" : end }; //发送数据 cal.postMessage(JSON.stringify(data)); cal.onmessage = function (evnet){ alert(event); } }
并行的两条Worker不能互相通讯,但Wroker可嵌套.
WebSocket: 服务器主动推送信息/客户端实时推送数据到服务器
6.1 跨文档通讯
window对象新增方法
html想发送要作
html想接收要作
//source.html var targetWin = window.open("接收方url",'_blank','windth=400,height=300'); targetWin.onload =function(){ targetWin.postMessage("传输消息","接收方域名"); } window.onmessage =function(event){ //忽略其余域名发送的消息 if(event.orgin !="指定域名"){ return ; } alert(event.data); } //接收页面.html window.onmessage = function(event){ //忽略其余域名发送的消息 if(event.orgin !="指定域名"){ return ; } alert("接收到消息拉!"+event.data); event.source.postMessage("回传消息",event.origin); }
结果:
alert(接收到消息拉!传输消息);
alert(回传消息);
注意!必定要判断发送方的域名!!!!!必定要判断发送方的域名!!!!!必定要判断发送方的域名!!!!!
之前方案:
WebSocket方法
WebSocket监听事件
WebSocket属性
WebSocket与服务器通讯步骤
客户端代码:
var web_socket =new WebSocket("ws://域名:端口"); web_socket.onopen =function(){ web_socket.onmessage =function(event){ document.getElementById('show').innerHTML += event.data +"</br>" } }; var sendMsg =function(val){ var inputElement = document.getElementByID('msg'); webSocket.send(inputElement.value); inputElement.value=""; } ...
服务端代码
<article class="post" > import java.io.*; import java.net.*; import java.nio.charset.Charset; import java.security.MessageDigest; import java.util.regex.*; import java.util.*; import sun.misc.BASE64Encoder; public class ChatServer { // 记录全部的客户端Soccket public static List<Socket> clientSockets = new ArrayList<Socket>(); public ChatServer()throws IOException { // 建立ServerSocket,准备接受客户端链接 ServerSocket ss = new ServerSocket(30000); while(true) { // 接收到客户端链接 Socket socket = ss.accept(); // 将客户端Socket添加到clientSockets集合中 clientSockets.add(socket); // 启动线程 new ServerThread(socket).start(); } } public static void main(String[] args) throws Exception{ new ChatServer(); } } class ServerThread extends Thread { private Socket socket; public ServerThread(Socket socket) { this.socket = socket; } public void run() { try { // 获得Socket对应的输入流 InputStream in = socket.getInputStream(); // 获得Socket对应的输出流 OutputStream out = socket.getOutputStream(); byte[] buff = new byte[1024]; String req = ""; // 读取数据,此时创建与WebSocket的"握手"。 int count = in.read(buff); // 若是读取的数据长度大于0 if(count > 0) { // 将读取的数据转化为字符串 req = new String(buff , 0 , count); System.out.println("握手请求:" + req); // 获取WebSocket的key String secKey = getSecWebSocketKey(req); System.out.println("secKey = " + secKey); String response = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: " + "websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: " + getSecWebSocketAccept(secKey) + "\r\n\r\n"; System.out.println("secAccept = " + getSecWebSocketAccept(secKey)); out.write(response.getBytes()); } int hasRead = 0; // 不断读取WebSocket发送过来的数据 while((hasRead = in.read(buff)) > 0){ System.out.println("接收的字节数:" + hasRead); /* 由于WebSocket发送过来的数据遵循了必定的协议格式, 其中第3个〜第6个字节是数据掩码。 从第7个字节开始才是真正的有效数据。 所以程序使用第3个〜第6个字节对后面的数据进行了处理 */ for (int i = 0 ; i < hasRead - 6 ; i++ ){ buff[i + 6] = (byte) (buff[i % 4 + 2] ^ buff[i + 6]); } // 得到从浏览器发送过来的数据 String pushMsg = new String(buff , 6 , hasRead - 6 , "UTF-8"); // 遍历Socket集合,依次向每一个Socket发送数据 for (Iterator<Socket> it = ChatServer.clientSockets.iterator() ; it.hasNext() ;) { try { Socket s = it.next(); // 发送数据时,第一个字节必须与读到的第一个字节相同 byte[] pushHead = new byte[2]; pushHead[0] = buff[0]; // 发送数据时,第二个字节记录发送数据的长度 pushHead[1] = (byte) pushMsg.getBytes("UTF-8").length; // 发送前两个字节 s.getOutputStream().write(pushHead); // 发送有效数据 s.getOutputStream().write(pushMsg.getBytes("UTF-8")); } catch (SocketException ex) { // 若是捕捉到异常,代表该Socket已经关闭 // 将该Socket从Socket集合中删除 it.remove(); } } } } catch (Exception e) { e.printStackTrace(); } finally { try { // 关闭Socket socket.close(); } catch (IOException ex) { ex.printStackTrace(); } } } // 获取WebSocket请求的SecKey private String getSecWebSocketKey(String req) { //构建正则表达式,获取Sec-WebSocket-Key: 后面的内容 Pattern p = Pattern.compile("^(Sec-WebSocket-Key:).+", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); Matcher m = p.matcher(req); if (m.find()) { // 提取Sec-WebSocket-Key String foundstring = m.group(); return foundstring.split(":")[1].trim(); } else { return null; } } // 根据WebSocket请求的SecKey计算SecAccept private String getSecWebSocketAccept(String key) throws Exception { String guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; key += guid; MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(key.getBytes("ISO-8859-1") , 0 , key.length()); byte[] sha1Hash = md.digest(); BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(sha1Hash); } } [javascript](http://mzkmzk.github.io/blog/categories/javascript/) </article> <a class="addthis_button_facebook_like" fb:like:layout="button_count" ></a><a class="addthis_button_tweet" ></a>
【我有一个前端学习交流QQ群:328058344 若是你在学习前端的过程当中遇到什么问题,欢迎来个人QQ群提问,群里天天还会更新一些学习资源。禁止闲聊,非喜勿进。】