#head-first-html5
##window.onload
window.onload = init;
function init() { //通常需要在页面完全加载完之后再执行js代码,因为页面没加载完,DOM都没有,你执行个蛋?
var planet = document.getElementById("greenplanet");
planet.innerHTML = "Red Alert: hit by phaser fire!";
}
##插入元素到DOM
var songItem = document.createElement("li");//新建元素,传入类型
songItem.innerHTML = songName;//设置新元素的文本,用innerHTML
var playlist = document.getElementById("playlist");//获取希望插入的元素
playlist.appendChild(songItem);//用appendChild()函数把新元素插入到希望插入的元素
##局部变量和全局变量
函数体外声明的,是全局变量
var avator;
var levelThreshold = 1000;//全局变量,页面链接到其它脚本,它们也会看到这些全局变量
function getScore(points) {
var score; //局部变量
for (var i = 0; i < levelThreshold; i++) {
//code here
}
return score;
}
var beanCounter = 10; //全局变量
function getNumberOfItems(ordertype) {
var beanCounter = 0; //和全局变量同名,将在此函数体内覆盖全部变量
if (ordertype == "order") {
//do some stuff with beanCounter...
}
return beanCounter;
}
##函数
function addOne (num) {
return num + 1;
}
var plusOne = addOne; //把addOne赋到一个新变量plusOne
var result = plasOne(1); //plasOne赋为一个函数,所以可以调用它并提供一个整型参数1
###函数可以没有名字
function(num) {
return num + 1;
}
//同样地,把这个匿名函数赋给一个变量
var f = function(num){
return num + 1;
}
//然后可以使用这个变量来调用函数
var result = f(1);
###将函数作为值能够做什么
function init() {
alert("you rule!");
}
window.onload = init; //如果函数名后面使用了小括号,比如init(),就是说你希望调用函数init。如果只是使用名字而没有小括号,就会把这个函数值赋给onload属性。
//直接把一个匿名的函数赋给window.onload属性
window.onload = function() {
alert("you rule!");
}
##创建对象
//将对象赋至一个变量时,会向变量提供这个对象的引用。它并不“保存”对象本身,所以,调用一个函数并传入一个对象时,实际上只是传递了对象引用--类似于一个指针。这个引用的副本会传递到形参,它指向原来的对象
var fido = {
name: "Fido", //类似字典的组织方式,中间用逗号间隔,!!!逗!!!号!!!不是分号!!!
weight: 40,
breed: "Mixed",
loves:["walks", "fetching balls"]//最后一个属性不用加逗号了,嗯
}; //别看它这么长,占了4行,这实际上还是一个赋值语句,需要加分号。
###可以用对象做的一些事情
if (fido.weight > 35) { //点语法访问对象属性
alert("WOOF");
} else {
alert("yip");
}
var breed = fido["breed"] //类似字典的key-value风格访问对象属性
if (breed = "mixed") {
alert("Best in show");
}
fido.weight = 70; //改变对象属性
fido.breed = "Chawalla/Great Dane mix";
fido.loves.push("Chewing bones"); //向对象属性(数组)增加元素,使用push()函数
var prop;
for (prop in fido) { //枚举对象属性
alert("Fido has a " + prop + "property ");
if (prop == "name") {
alert("This is " + fido[prop]);
}
}
var likes = fido.loves; //处理对象数组
var likeString = "Fido likes ";
for (var i = 0; i < likes.length; i++) {
likeString += likes[i];
}
alert(likeString);
function bark(dog){ //向函数传入一个对象
if (dog.weight > 25) {
alert("WOOF");
} else {
alert("yip");
}
}
bark(fido);
//任何时刻都可以增加或删除属性
//要向一个对象增加属性,只需要为一个新属性赋一个值
fido.age = 5; //从现在开始,fido就有了一个age属性
delete fido.age;//删除一个对象的属性,删除成功delete表达式会返回true
function loseWeight(dog) {
dog.weight = dog.weight - 10;
}
loseWeight(fido); //把fido传入loseWeight时,赋给dog形参的是引用的一个副本(fido是对象的一个引用),而不是对象的副本,所以fido和dog指向同一个对象。
###对象中的函数
var baby = {
name: "Fido",
weight: 40,
breed: "Mixed",
loves:["walks", "fetching balls"],
//对象也可以有函数:对象中的函数,叫做方法
bark : function(){
alert("WOOF!!!");
}
};
//调用对象中的方法
baby.bark();
var movie3 = {
name:"Planet 2333",
type:"KeHuanPian",
level:3,
showTime:["5:00am","6:30pm","9:00pm"],
getNextShowing:function() {
var now = new Date().getTime();
//对象中的方法要使用this关键字访问对象自身的属性。相当于Objective-C的self
for (var i = 0;i < this.showTime.length; i++) {
var showtime = getTimeFromString(this.showTime[i]);
if ((showtime - now) > 0) {
return "Next showing of " + this.name + " is " + this.showTime[i];
}
}
return null;
}
};
var newNextShowing = movie3.getNextShowing();
alert(newNextShowing);
//按照144行的方式构造一个movie对象,每一个movie对象都会有一大段重复的getNextShowing方法代码
// 这里可以使用***构造函数***来解决
//构造函数的名字,按照约定,首字母要大写,形参取我们希望的对象属性值
function Dog(name, breed, weight) { //可以想象成Objective-C里的 initWithName:Breed:Weight
this.name = name;
this.breed = breed;
this.weight = weight;
this.bark = function(){
if (this.weight > 25) {
alert(this.name + " says WOOF!");
} else {
alert(this.name + "says Yip!");
}
};
}
//调用构造函数前要加上关键字new
var krake = new Dog("Krake","Mixed",47);
var tiny = new Dog("Tiny","Chawalla",8);
var clifford = new Dog("Clifford","Bloodhound",65);
krake.bark();//一旦得到对象,就可以调用它们的bark方法让每个Dog叫
tiny.bark();
clifford.bark();
//构造movie
function Movie(title, genre, rating, showtimes) {
this.title = title;
this.genre = genre;
this.rating = rating;
this.showtimes = showtimes
this.getNextShowing = function(){
var now = new Date().getTime();
for (var i = 0; i < this.showtimes.length; i++) {
var showtime = getTimeFromString(this.showtimes[i]);
if ((showtime - now) > 0) {
return "Next showing of " + this.title + " is " + this.showtimes[i];
}
}
};
}
var krakeMovie = new Movie("泰坦尼克号","爱情动作片",5,["3:00pm","5:00pm","8:00pm"]);
//window对象相当于全局环境,所以alert()不加 window. 前缀也可以顺利解析
alert(krakeMovie.getNextShowing());
##第五章-爸爸去哪儿(地理位置API) ###Geolocation.getCurrentPosition()函数
function getMyLocation() {
if (navigator.geolocation) { //利用这个检查确保浏览器支持地理定位API,如果存在这个对象,说明浏览器支持这个API
//当geolocation确定了你的位置,就会调用传入的这个函数
navigator.geolocation.getCurrentPosition(displayLocation, displayError,options);//追踪位置时需要注释这一行,添加下面4行 //displayLocation函数就是将要操纵位置的处理程序
} else {
alert("Oops, no geolocation support");
}
}
###成功处理函数success handler
function displayLocation(position) {//浏览器得到一个位置时就会调用这个函数。getCurrentPosition会传递一个位置(position对象)到这个函数,包含经度和纬度
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
var div = document.getElementById("location");
div.innerHTML = "You are at Latitude: " + latitude + ", Longitude: " + longitude;
div.innerHTML += "(with " + position.coords.accuracy + " meters accuracy)";//精度
div.innerHTML += "(found in " + options.timeout + " milliseconds)";
var km = computeDistance(position.coords, ourCoords);//计算距离
var distance = document.getElementById("distance");
distance.innerHTML = "You are" + km + "km from the wickedlySmart HQ";
}
###失败处理函数failed handler
function displayError(error) { //geolocation会在确定位置失败时向这个函数传入一个error对象。其中包含一个数值码,描述了未能确定浏览器位置的原因。
var errorType = {
0: "Unknown error",
1: "Permission denied by user",
2: "Position is not available",
3: "Request timed out"
};
var errorMessage = errorType[error.code];//error对象有一个code属性,其中包含一个0-3的数。根据code属性的不同,把一个错误消息串赋给一个新变量
if (error.code == 0 || error.code == 2) {
errorMessage = errorMessage + " " + error.message;
}
var div = document.getElementById("location");
div.innerHTML = errorMessage;
options.timeout += 100;
navigator.geolocation.getCurrentPosition(displayLocation,displayError.options);
div.innerHTML += "...checking again with timeout= " + options.timeout;
}
###getCurrentPosition的第三个参数:
var positionOptions = {
enableHighAccurary: false, //是否开启高精度
timeout: Infinity, //超时时长
maximumAge:0 //缓存时间,例如,设置为60000 (60s),60秒内第二次求位置会返回原来的值,不会重新求
}
###追踪位置
var watchId = null; //通过这个id来clear追踪状态
function watchLocation(){
watchId = navigator.geolocation.watchPosition(displayLocation, displayError);
alert("正在追踪位置");
}
function clearwatch() {
if (watchId) {
navigator.geolocation.clearWatch(watchId);
watchId = null;
alert("停止追踪位置");
}
}
##第六章
###如何从javascript创建请求 ####XMLHttpRequest
var url = "http://someserver.com/data.json"; //创建一个目标url,告诉浏览器要到哪里找我们想要的数据
var request = new XMLHttpRequest(); //创建一个XMLHttpRequest请求对象
request.open("GET",url)//这个request对象将使用GET方式获取url的请求。open用一个URL建立一个请求,并告诉这个请求对象要使用哪种请求,以便XMLHttpRequest验证连接。
request.onload = function() { //数据到达时,调用这个处理函数
if (request.status == 200) { //http响应码200表示请求没有错误
alert(request.responseText);//HTTP GET获取到数据可以在request对象的responseText属性中找到
}
};
request.send(null); //告诉请求对象去获取数据。send()会把请求发送到服务器,如果不打算发送任何数据,就传入null。
###JSON ####JSON.stringify()把数据转化为json格式
var plan9Movie = new Movie("Plan 9 from Outer Space","Cult Classic",2,["3:00pm","5:00pm","11:00pm"]); //创建一个对象
var jsonString = JSON.stringify(plan9Movie);//转化为json格式的串
alert(jsonString);
####JSON.parse()把json数据转化为javascript对象
var jsonObject = JSON.parse(jsonString);//json串转化为对象
alert("JSON movie is " + jsonObject.title);
###tips: 如何在Mac上启动localhost本地服务器
window.onload = function() {
//var url = "http://gumball.wickedlysmart.com";
var url = "http://localhost/sales.json"; //测试时需要在浏览器输入http://localhost/mightygumball.html,直接打开mightygumball.html将无法获取json数据
var request = new XMLHttpRequest();
request.open("GET", url);
request.onload = function() {
if (request.status == 200) {
updateSales(request.responseText);
}
};
request.send(null);
}
function updateSales(responseText) {
var salesDiv = document.getElementById("sales");
var sales = JSON.parse(responseText); //转化为javascript对象
for (var i = 0; i < sales.length; i++) { //迭代处理每一个数组元素
var sale = sales[i];
var div = document.createElement("div"); //对每个元素,创建一个div,设置class属性以便css调整样式
div.setAttribute("class","saleItem");
div.innerHTML = sale.name + " sold " + sale.sales + " gumball";
salesDiv.appendChild(div);
}
}
##浏览器安全策略
###javascript 代码可以接受的行为 用户对一个页面(blablabla.com)作出请求 页面需要得到blablabla.com的一些数据,所以对这些数据作出XMLHttpRequest ###javascript 代码不能接受的行为(XMLHttpRequest跨域请求) 浏览器对blablabla.com上的一个页面作出请求 代码希望从一个来源得到数据,也就是hehehe.com,嗯,这是不!!行!!的!! XMLHttpRequest向hehehe.com请求数据-->浏览器看的这个请求指向与页面不同的域,就会停下,请求被拒绝-->blablabla.com的服务区根本没有看到请求,在它看到请求之前,浏览器的安全策略已经中止了这个请求 (简单地说,你丫百度的跑来我大谷歌请求数据?滚!!!)
###JSONP-一种使用<script>获取数据的方法
浏览器不允许你对原先提供页面的域以外的其他域发出XMLHttpRequests请求
如果从某个域提供页面,安全策略要求不能从另一个域获取数据
当我们需要从其他域获取数据时,可以这样:
mightygumball.html
<!doctype html>
<html lang="en">
<head>
<title>Mighty Gumball</title>
<meta charset="utf-8">
<script src="mightygumball.js"></script>
<link rel="stylesheet" href="mightygumball.css">
</head>
<body>
<h1>Mighty Gumball Sales</h1>
<div id="sales">
</div>
<script src="http://gumball.wickedlysmart.com/gumball/gumball.com/?callback=updateSales"></script><!--链接外部javascript-->
</body>
</html>
解析到数据后回调updateSales函数进行处理(?callback=updateSales)
mightygumball.js
function updateSales(sales) { //返回的新数据不再是一个json串,而是一个对象。
var salesDiv = document.getElementById("sales");
for (var i = 0; i < sales.length; i++) { //迭代处理每一个数组元素
var sale = sales[i];
var div = document.createElement("div"); //对每个元素,创建一个div,设置class属性以便css调整样式
div.setAttribute("class","saleItem");
div.innerHTML = sale.name + " sold " + sale.sales + " gumball";
salesDiv.appendChild(div);
}
}
####安全问题 如果向一个恶意web服务发出一个JSONP请求,响应中可能包含你不想要的代码,而且浏览器会执行这些恶意代码。所以在链接前需要确保信任这个服务。
###定时器 ####setInterval(handleRefresh,timeInterval)方法
setInterval(imfire, 3000);//每隔3秒钟,执行一次imfire函数
function imfire(){
alert("I'm fire!");
}
###动态插入<script>元素
setInterval(handle, interval)
getElementsByTagName(tag)
replaceChild(new,old)
setAttribute(attributeName, value)
载入脚本,调用setInterval()
window.onload = function() {
var url = "http://gumball.wickedlysmart.com/gumball/gumball.com";
setInterval(refresh, 3000); //setInterval()返回一个id标识这个定时器,把这个id保存在一个变量里,以后可以通过传递id到clearInterval方法停止它
}
setInterval()调用refresh()
如果多次请求,可以在JSONP请求URL的末尾使用一个随机数(这是是random=blablabla),使浏览器不会缓存这个相应
function refresh() {
var url = "http://gumball.wickedlysmart.com/gumball/gumball.com/?callback=updateSales" + "&lastreporttime" + lastReportTime + "&random=" + (new Date()).getTime(); //url放在这里
var newScriptElement = document.createElement("script");//新建一个script元素
newScriptElement.setAttribute("src",url);//设定新script的src和id
newScriptElement.setAttribute("id","jsonp");
var oldScriptElement = document.getElementById("jsonp");//看看有没有这个元素
var head = document.getElementsByTagName("head")[0]; //返回与给定标记名匹配到元素数组
if (!oldScriptElement) {//如果没有
head.appendChild(newScriptElement); //增加到head
} else {//如果已经存在
head.replaceChild(newScriptElement, oldScriptElement); //替换掉 -->replaceChild(new, old)
//如果只是用新的url替换src属性,浏览器不会把它当做一个新元素,所以不会发出请求,要强制浏览器作出请求,必须创建这个全新的script元素。替换掉整个<script>元素。这种技术称为“脚本插入”
}
}
脚本插入后调用url里传入的回调函数updateSales
function updateSales(sales) { //返回的新数据不再是一个json串,而是一个对象。
var salesDiv = document.getElementById("sales");
for (var i = 0; i < sales.length; i++) { //迭代处理每一个数组元素
var sale = sales[i];
var div = document.createElement("div"); //对每个元素,创建一个div,设置class属性以便css调整样式
div.setAttribute("class","saleItem");
div.innerHTML = sale.name + " sold " + sale.sales + " gumball";
salesDiv.appendChild(div);
}
if (sales.length > 0) {
lastReportTime = sales[sales.length -1].time;
}
}