基礎事件委託 | 歷史管理 | firebug | 快速排序 |遞歸 筆記
事件委託:利用冒泡原理,把事件添加至父級上,觸發執行效果;
好處:1、提高性能;2、新添加元素還會有之前的事件,如新浪圍脖發布效果;
操作要點:1、添加事件到父級;2、找到當前的事件源,在事件源觸發;
兼容寫法: ie:window.event.srcElement 標準:window.event.target
之後使用nodeName判斷標籤源;
<input type="button" value="add" id="inp"/>
<ul id="ul1">
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
var ul = document.getElementById('ul1')
var li = ul.getElementsByTagName('li')
ul.onmouseover = function (ev) {
var ev = ev || event;
var target = ev.target || ev.srcElement
if (target.nodeName.toLowerCase() == 'li') {
target.style.background = 'red'
}
}
ul.onmouseout = function (ev) {
var ev = ev || event;
var target = ev.target || ev.srcElement //當前操作事件源,比如移動到li即li,移動到ul即ul
if (target.nodeName.toLowerCase() == 'li') { //只移動到li觸發
target.style.background = ''
}
}
//新添加元素還會有之前的事件,如使用for新加元素不會綁定事件
var inp = document.getElementById('inp')
var i = 0;
inp.onclick = function () {
i++;
var oli = document.createElement('li')
oli.innerHTML = 555 * i;
ul.appendChild(oli);
}
歷史管理
1、onhashchange:事件,當hash有變化時觸發;
2、histoty:事件
存:pushState(數據,標題[未實現],網址顯示)
讀:onpopState事件 event state;注意:網址顯示虛假,使用時須服務器指定
onhashchange簡陋例子
<input type="button" value="生成隨機數" id="inp"/>
<div id="box"></div>
var inp = document.getElementById('inp')
var box = document.getElementById('box')
inp.onclick = function () {
var num = randomNum(49, 7); //49選7
box.innerHTML = num;
window.location.hash = num; //window.location.hash添加值
}
window.onhashchange = function () {
var num = window.location.hash.substring(1) || '';
box.innerHTML = num; //當改變時觸發;
}
//隨機數生產方法封裝
function randomNum(alls, now) {
var arr = []
var Newarr = []
for (var i = 1; i <= alls; i++) {
arr.push(i);
}
for (var i = 0; i < now; i++) {
Newarr.push(arr.splice(Math.floor(Math.random() * arr.length), 1))
}
return Newarr;
}
網址變更
var inp = document.getElementById('inp')
var box = document.getElementById('box')
var obj = {} //利用對象
inp.onclick = function () {
var num = randomNum(49, 7);
box.innerHTML = num;
var oRD = Math.random(); //生成隨機數 0.xxxxxxx
obj[oRD] = num; //對像對應關係,每一個隨機數對應每一個num;
window.location.hash = oRD; //實際上相當於處理下標元素
}
window.onhashchange = function () {
var num = obj[window.location.hash.substring(1) || ''];
box.innerHTML = num; //所以這裏需要套obj, '' 為防止undefined
}
histoty例子
var inp = document.getElementById('inp')
var box = document.getElementById('box')
var i = 1;
inp.onclick = function () {
var num = randomNum(49, 7);
box.innerHTML = num;
history.pushState(num, '', i++); //存到history,這裏第三個參數為可選,可不填寫
}
window.onpopstate = function (e) { //當改變時執行讀取
e = e || event
var num = e.state || '';
box.innerHTML = num;
}
跨域
ajax: XMLHttpRequest();不能跨域
jsonp:json + padding [把json放在盒子裏]<blockquote>
1、document.domain = 'xx.com'
2、服務器代理:XMLHttpRequest代理文件
3、script標籤:jsonp
4、location.hash
5、window.name
6、flash
7、html5 postMessage
</blockquote>
function createJS(sUrl){
var _Script = document.createElement('script')
_Script.src = sUrl;
document.getElementsByTagName('head')[0].appendChild(_Script);
}
createJS('jsonp.js')
//createJS('jsonp.js?callback = box')
function box(){
alert(json.name);
}
//box({name:elmok}) 放到jsonp.js文件裏
hash值
<iframe src="xxx.php#key1=value1&key2=value2" frameborder="0"></iframe>
parent.location.hash = self.location.hash; //ie chrome不支持
firebug
console.group('')
console.log('abc')
console.groupEnd('')
console.dirxml(box) //顯示當前元素代碼結構
console.assert(20 == '20') //斷言假提示,成功不提示
function a(){return b()};
function b(){return c()};
function c(){console.trace();return 1}; //當前fn執行過程
a();
console.time('計時器')
for(var i=0;i<10000;i++){
}
console.timeEnd('計時器') //計算fn執行時間
function a() { //部分fbug無法顯示!
for (var i = 0; i < 10; i++) {
b(); //調用10次b
}
for (var i = 0; i < 5; i++) {
c(); //調用5次c
}
function b() {
var b = 10;
}
function c() {
var c = 5;
}
}
console.profile();
a();
console.profileEnd();
快速排序
30 12 5 6 9 18 57 2
取基准點9,9跟其他數比, [小於] 9 [大於]
5 6 2 9 30 12 18 57
取基准點 30 [小於] 30 [大於]
5 6 2 9 12 18 30 57
...以此類推
利用遞歸進行下次比較
//方法封裝
function quickSort(arr) {
if (arr.length <= 1) { //有可能為0
return arr;
}
var num = Math.floor(arr.length / 2) //向下取整,找到中間數
var numV = arr.splice(num, 1); //找到基準點的數值
var left = []; //存小於基准點的值
var right = []; //存大於基準點的值
for (var i = 0; i < arr.length; i++) {
if (arr[i] < numV) {
left.push(arr[i]);
}
else {
right.push(arr[i]);
}
}
//以上一次操作,下面再利用遞歸原理
return quickSort(left).concat([numV], quickSort(right));
//左邊.concat(基准數,右邊)
}
alert( quickSort([30,12,5,6,9,18,57,2]) )
函数声明与函数表达式
函数声明:function 函数名(){}
函数表达式:function 函数名(){},命名与匿名表达式;
function aaa() {} //函数声明
var a = function aaa() {} //命名函数表达式
var b = function () {} //匿名函数表达式
(function aaa() {}) //函数表达式
~function aaa() {} //函数表达式
-function aaa() {} //函数表达式
+function aaa() {} //函数表达式
~function aaa() {} //函数表达式
区别:1、函数表达式可直接后面加括号执行,函数声明不行;
2、函数声明可以被提前解析出来;<br />
在一些语句中若想执行不同函数时,不要用函数声明,用函数表达式;
if (true) {
function bbb() {
alert(1)
}
}
else {
function bbb() {
alert(2)
}
}
a(); //ff、IE11正常弹1,其它弹2 [因为函数声明被预解析],
所以修改为:
if (true) {
var a = function bbb() {
alert(1)
alert(typeof bbb)
}
}
else {
var a = function bbb() {
alert(2)
}
}
a();//正常都弹1
bbb() //IE8下能弹出2,其它出错 [IE8下解析成两个函数 a(), bbb()]bbb()外面找不到,里面可找到,外面不要去调用函数表达式;
對象引用
遞歸算法:1、函數調用函數,永遠不會return,遞的過程
2、最後一次判斷一個終止條件,可以執行歸的動作。終止條件必須寫在最前面
典型例子:階乘
function factorial(n) {
if (n == 1) { return 1 } //條件,最後一次為1 終止條件寫在最前面
return n * factorial(n - 1);
}
console.log(factorial(5));
var a = 5;
var b = a;
b += 3;
alert(b) //b的改变不会影响到a,赋值类型
var arr = [1,2,3]
var arrN = arr //arrN與arr指向同一地址
arrN.push(4)
console.log(arrN); //[1,2,3,4]
console.log(arr); //[1,2,3,4] 影响到arr,对象和函数都是地址引用的关系
var arr = [1,2,3]
var arrN = arr
arrN = [1,2,3,4] //相当于赋另一块地址给arrN,arrN重新战胜一块地址,与arr分离
console.log(arrN); //[1,2,3,4]
console.log(arr); //[1,2,3]
var obj = {
a: 10
}
var objN = obj;
objN.a = 20;
console.log(obj.a); //20,复制对象的问题,改变objN,同时影响到obj*/
第一種:淺拷貝
var obj = {
a: 10
}
function copyO(obj) {
var newO = {
};
for (var attr in obj) {
newO[attr] = obj[attr]; //所有值都复制给新对象
}
return newO
}
var objN = copyO(obj);
objN.a = 20;
console.log(obj.a); //10 只有一層不會影響
第二種:深拷貝
var obj = {
a: {b: 10} // 可能會有無數層
}
function deepcopyO(obj) { //深拷貝 遞歸
if (typeof obj != 'object') { //什麼時候不是對象即能返回
return obj;
}
var newO = {};
for (var attr in obj) {
newO[attr] = deepcopyO(obj[attr]); //進入下一層拷貝
}
return newO
}
var objN = deepcopyO(obj);
objN.a.b = 20;
console.log(obj.a.b); //10,再多層也不影響