代碼筆記
JavaScript
封裝自己的log函數
-
eg
- 普通封裝
var log = function() { // arguments是保存函數所有參數的值 console.log.apply(console,arguments) }
- 箭頭函數封裝
var log = (args) => { console.log(...args) } log([1,2,3]) -> 1 2 3
穿衣服:這樣才能真正看到變量是什么
log(`(${變量})`)
- 作用
- 確保代碼執行
- 打印所有能打印的值
測試函數(套路)
- 定義一個通用判斷函數
var ensure = function(condition,message) {
if (!condition) {
log(message)
}
}
// 增強版
var ensureEqual = function(a,b,message) {
if(a !== b){
log(`測試失敗,a:${a}和b:${b}不相等,${message}`)
}
}
- 定義一個測試函數
var testSum = function() {
let numbers = [1,2,3,4]
let value = 10
ensure(value === sum(numbers),'sum 錯誤')
ensure(1 === sum([1]),'sum 1 錯誤')
}
對象(字典)
eg :var op = {'fuck':1}
- 通過點運算符訪問
log(op.fuck) ==> 1
- 通過中括號訪問
log(op['fuck']) ==> 1
DOM(文檔對象模型)
- 查找元素
document.querySelector(選擇器) // 查找一個元素
document.querySelectorAll(選擇器) // 查找全部元素
- 操作元素屬性
- 設置元素的屬性: setAttribute(屬性名,值)
- 獲得元素的屬性值:getAttribute(屬性名)
- 判斷屬性是否存在 : hasAttribute(屬性名)
- 刪除某個屬性 : removeAttribute(屬性名)
- 所有屬性 : .attributes
-
操作元素(創建、刪除、修改)
- 創建:document.createElement(元素)
- 修改:用appendChild增加子元素
父元素.appendChild(元素)
- 刪除
父元素.removeChild(元素) 元素.remove() 元素.parenElement可以得到自己的父元素
- 插入一段html
元素.insertAdjavenHtml('查文檔',html語句)
事件
- 添加事件addEventListener(事件名字,事件處理函數)
// 給多個元素掛上同一個事件
// 選擇多個元素使用函數 querySelectorAll
var buttons = document.querySelectorAll('.radio-button')
// 循環遍歷每個元素, 并且綁定點擊事件
for (var i = 0; i < buttons.length; i++) {
var buttonFuck = buttons[i]
buttonFuck.addEventListener('click', function(event){
// 注意, 這次我們直接定義了函數作為參數傳遞, 這樣做是合法的
// 另外, 我們增加了一個 event 參數
// 瀏覽器會給事件響應函f數傳遞一個參數, 它代表了事件本身 (指buttonFuck的click)
// 我們可以用 event.target 取出響應事件的元素 (buttonFuck)
var self = event.target
// clearActive 函數是我們自己定義的
// 目的是刪除其他元素的 active class
clearActive()
// add 可以增加一個 class
self.classList.add('active')
})
}
var clearActive = function() {
var active = document.querySelector('.active')
if (active != null) {
// 使用 classList 可以訪問一個元素的所有 class
// remove 可以刪除一個 class
active.classList.remove("active")
}
}
- 事件冒泡/捕獲
-
事件冒泡
- 微軟做的
- 定義:事件發生后一直往最外層。(最底層先觸發)
- 阻止事件冒泡:event.cancelBubble = true
-
事件捕獲
- 網景公司做的
- 就是添加事件addEventListener函數的第三個參數,設置為true的時候意思為useCapture
- 最外層攔住了事件,再看看下一級元素有沒有觸發了的,有就傳遞
- 事件觸發順序會與事件冒泡反過來
它們同時發生的時候,先進行事件捕獲,再進行事件冒泡
-
樣式開關函數的套路
// 樣式開關函數套路
var toggleClass = (element,className) =>{
if(element.classList.contains(className)) {
element.classList.remove(className)
} else {
element.classList.add(className)
}
}
序列化和反序列化
// 序列化和反序列化套路
var infoList = ['b','f','q']
var s = JSON.stringify(infoList)
log('序列化之后的s ',typeof s ,s)
var a = JSON.parse(s)
log('反序列化之后的s ',typeof a ,a)
時間標準庫
// 時間標準庫
// ===
// 常用用法如下
var d = new Date()
d.getFullYear()
年份, 2016
d.getMonth()
月份, 0-11
d.getDate()
日期, 1-31
d.getHours()
小時, 0-23
d.getMinutes()
分鐘, 0-59
d.getSeconds()
秒數, 0-59
d.getMilliseconds()
毫秒, 0-999
d.getDay()
星期幾, 0-6
事件取消
event.preventDefault()
老javascript類
- 一個例子
var Student = function(name,sex){
this.name = name
this.sex = sex
this.say=()=>{
log('我是一個類')
}
}
// 創建一個類的實例
var s = new Student('g','man')
s.say() -> 我是一個類
// prototype可以給所有實例加上一個值,函數盡量在這里定義
Student.prototype.get = ()=>{
log('所有的實例都能擁有這個函數 ',this.name)
}
s.get() -> 所有的實例都能擁有這個函數 g
- ps:可以擴展內置的類
String.prototype.say = ()=>{
log('你敢用我嗎? ')
}
''.say() -> 你敢用我嗎?
拆分函數的依據
- 上層函數不關心下層函數的難點
- 描繪what 不是描繪how
編碼
瀏覽器的url是有規范的 eg:空格會變成 %20
-
javaScript里
- URL
// 這個函數就是URL轉碼的函數 encodeURIComponent(需要轉碼的字符串) // 這個是URL解碼的函數 decodeURIComponent(需要解碼的字符串)
- base64
jquery
- 找jquery
- 常見用法
-
選擇器
- 類似querySelector函數
$('選擇器')
- find
// find函數只能用在jq對象上 var form = $('.form') form.find('#id-input-add')
-
closest函數
- closest(選擇器) : 往自己的父節點找,沒找到就一直往上找
- 例子
$(選擇器).on(事件名,function(event)=>{ // dom對象轉成jq對象 var 元素 = $(event.target) // 刪除自己 元素.closest(選擇器).remove() })
-
取值
- val
// 取值(目前特指input) var value = $(選擇器).val()
- text :返回text內容,如果text(有參數)就改成你設的參數
// 無參數 var 元素 = $(選擇器) var t = 元素.text() log(t) -> hello // 有參數 元素.text('fuck') log(元素.text()) -> fuck
- html :返回帶標簽的內容,帶參數就設置為你設的參數
// 無參數 var 元素 = $(選擇器) var t = 元素.html() log(t) -> <h1>hello</h1> // 有參數 元素.html('<h2>hello</h2>') log(元素.html()) -> <h2>hello</h2>
-
事件委托
var 父節點 = $(選擇器).on(事件名,響應對象,回調函數)
-
dom操作
- 添加元素
// 添加元素 $(選擇器).append(元素)
- 刪除元素
$(選擇器).remove()
- 刪掉子元素
$(選擇器).empty()
- 顯示、隱藏、開關
// 顯示 $(選擇器).show() // 隱藏 $(選擇器).hide() // 開關 $(選擇器).toggle()
-
class操作
- addClass
- removeClass
- toggleClass
-
屬性、特性操作
attr :查屬性的值
prop
-
data
- 設置數據:對任意一個元素掛上data-名字來存數據
- 用法
- html
<div data-id='401'/> <div data-id='402'/>
- javaScript
var divList = $(選擇器) // dom取法 var domDiv = divList[0] var id = domDiv.dataset.id log(id) -> 401 // jq取法 var jqDiv = $(divList[0]) var id = jqDiv.data('id') log(id) -> 401
removeAttr 刪除一個屬性
-
事件
- on
$(選擇器).on(事件名,function(event)=>{ })
- change (暫時指input、下拉框)
$(選擇器).change(function(event)=>{ })
- event.target :要轉成jq才能使用jq的函數
-
數組方法
- each :簡化版的for
$(選擇器).each(function(i,element){ log('element ',i,element) })
- map 對數組每一個元素處理然后返回一個值,生成一個新的數組
var foo = [1,2,3,4,5] newFoo = $.map(foo,function(value){ return value*value }) log(newFoo) -> [1,4,9,16,25]
- grep 過濾,生成新數組
var foo = [1,2,3,4,5] newFoo = $.map(foo,function(value){ return value %2 == 0 }) log(newFoo) -> [2,4]
-
ajax
- 引入jq
var h = document.querySelector('head') h.insertAdjacentHTML('beforeend', '<script src="https://cdn.bootcss.com/jquery/3.2.1/core.js"></script>')
- 用法
$.ajax({ url:一個api地址, type:'get', contentType:'application/json', success:function(){ log(arguments) }, error:function(){ log(arguments) } })
- dataType
所有元素全部加載完回調
$('document').ready(function(){ })
-
高級一點的東西
-
bind 處理this的一個動態的this的問題
- 體現this會變的例子
var o = { foo: 1, bar: function(){ return this.foo } } var a = o.bar // 調用字典里的函數 o.bar() -> 1 // 調用a的時候,this變成里Windows a() -> undefined
- a函數的this被bind到了o上
var o = { foo: 1, bar: function(){ return this.foo } } var a = o.bar.bind(o) a() -> 1
-
apply(直接傳參數)和call(要一個個傳) 都是為了改變動態this的
- apply特殊用法
var log = function() { console.log.apply(console,arguments) }
- 普通用法
貓吃魚,狗吃肉,奧特曼打小怪獸。 有天狗想吃魚了 貓.吃魚.call(狗,魚) 狗就吃到魚了 貓成精了,想打怪獸 奧特曼.打小怪獸.call(貓,小怪獸) function cat() {} cat.prototype = { food: "fish", say: function() { alert("I love " + this.food) } } var blackCat = new cat blackCat.say() // 但是如果我們有一個對象 whiteDog = {food:"bone"} // 我們不想對它重新定義say方法 // 那么我們可以通過call或apply用blackCat的say方法: blackCat.say.call(whiteDog) /* 所以,可以看出call和apply是為了動態改變this而出現的, 當一個object沒有某個方法,但是其他的有, 我們可以借助call或apply用其它對象的方法來操作。 */
es6
-
擴展符號 ...可以解開數組
- eg1
var a = [1,2,3] var b = [...a,5] log(b) -> [1,2,3,5]
- 傳參數
var add = function(a,b,c){ return a+b+c } var numbers = [1,2,3] var value = add(...numbers) log(value) -> 6
- 復制一個數組
var a = [1,2,3] var b = [...a]
- 合并數組
var a = [1,2,3] var b = [4,5,6] var c = [7,8,9] var o = [...a,...b,...c]
-
解包(從python學來的)
- 賦值
var [a,b] = [1,3] log(a,b) -> 1 3
- 鬼畜賦值
var [a,b,_] = [1,2,3,4,5] log(a,b,_) -> 1 2 [3,4,5]
- 交換值
var a = 1 var b = 2 [a,b] = [b,a] log(a,b) -> 2 1
-
箭頭函數
- 跟c#的lambda差不多意思
- 蕭大說是垃圾
- 等價例子
// 兩者等價 var log1 = function(){} var log2 = ()=>{}
for…of循環
let iterable = [10, 20, 30];
for (let idx in iterable){
console.log(idx) // 依次輸出:0, 1, 2
}
for (let value of iterable){
console.log(value) // 依次輸出:10, 20, 30
}
-
新增的函數
-
Array.from()
- 任何有length屬性的都可以轉成真正的數組
var a = {length:3} var b = Array.from(a) log(b) -> [undefined,undefined,undefined]
- 如果它本身就是一個數組,會返回一個一摸一樣的數組
- 可以有第二個參數,類似map函數。對每一個元素處理再返回
數組填充 fill
var ['a','b','c'] = fill(7) -> [7,7,7]
- includes 判斷數組是否存在這個元素
-
if的條件一定不要是隱含條件
HTML
HTML5
* 游戲庫 phaser
普通HTML
CSS
CSS寫在哪里
- 內聯屬性寫CSS(不推薦)
<h1 style="color:red;" > hello gua </h1>
- <head> 標簽內的<style> 標簽
- <link> 標簽的外聯
選擇器
- 元素選擇器(標簽選擇器)
h1 {
background:blue;
}
- class 選擇器
.gua-title {
background: :blue;
}
- id選擇器
#id-h1 {
background: yellow;
}
CSS命名規矩 -- ( 屬性名-元素名-名稱 )
樣式優先級(從高到低)
- !important
h1 {
color:white !important;
}
- 內聯
- <style> 中的樣式
- link中的樣式
選擇器優先級
- !important
- 內聯
- id
- class
- 元素
盒模型
- 內容
- padding
- border
- margin
元素定位(position)
- 非 static 元素可以用top、left、bottom、right設置坐標
- relative :相對定位
- absolute :完全絕對定位,忽略其他的東西,往上浮動到非 static 的元素
- fixed :基于windows的絕對定位,不隨頁面滾動改變
display
- block : 獨占一行
- inline : 跟別人擠一行
- inline-block : 可以跟別人擠一行,并且可以設置寬度
- ps : block 屬性使得元素具有自己的盒模型
偽類選擇器
a::hover {
樣式
}
使得一個元素屏幕居中
.類 {
top: 50%;
position: relative;
transform: translateX(-50%)
}
改變元素的樣式可以通過改變class來完成
事件委托-子元素的事件,可以綁定在父級元素
- ps:子元素執行事件函數的時候,如果父元素也有這個事件函數,也會執行
- 一個例子,TODO程序
html
<html>
<head>
<meta charset="utf-8">
<style>
.done {
text-decoration: line-through;
}
</style>
</head>
<body>
<input id="id-input-value" type="text">
<button id="id-button-add">add</button>
<div id="id-div-Cell" class="cell">
<div>
<button class="overClass">over</button>
<button class="delClass">del</button>
<span contenteditable="true">test</span>
</div>
</div>
</body>
JavaScript
<script>
var log = function() {
console.log.apply(console,arguments)
}
let divCell = document.querySelector('#id-div-Cell')
divCell.addEventListener('click',(event)=>{
log('父元素調用這個函數了 ')
var item = event.target
if(item.classList.contains('overClass')) {
item.parentElement.classList.add('done')
} else if(item.classList.contains('delClass')) {
item.parentElement.remove()
}
})
var testButton = document.querySelector('.overClass')
testButton.addEventListener('click',()=>{
log('子元素調函數')
})
var addButton = document.querySelector('#id-button-add')
addButton.addEventListener('click',(event)=>{
log('event ',event.target)
let input_ = document.querySelector('#id-input-value')
let todo = input_.value
var t = newDiv(todo)
divCell.insertAdjacentHTML('beforeend',t)
})
var newDiv = (todo)=>{
t = `
<div>
<button class="overClass">over</button>
<button class="delClass">del</button>
<span contenteditable="true">${todo}</span>
</div>
`
return t
}
</script>
</html>
// 當點擊overButton的時候,會輸出 父元素調用和子元素調用
http協議
- 請求行或者響應行:決定做的事情的性質
- head和body是用空行隔開的
- 瀏覽器會解析head,body自己處理
掌握http有什么用?
-
可以用js動態抓取網頁內容
- 動態評論、加載數據
- 天氣預報
- 壁紙圖片庫
瀏覽器提供了使用 HTTP 協議收發數據的接口,名為 AJAX
瀏覽器安全問題
- 跨域
- file不能使用ajax
ajax
-
ajax請求的套路
- GET請求
// 創建一個ajax請求對象 var r = new XMLHttpRequest() // 注冊響應函數 r.onreadystatechange = ()=>{console.log('start begin ',r)} // 設置請求方法和請求地址(open第三個參數代表是否使用異步) r.open('GET','#signin',true) // 發送請求 r.send()
以下是打印的內容
start begin XMLHttpRequest {readyState: 2, ……} VM203:1 start begin XMLHttpRequest {readyState: 3, ……} VM203:1 start begin XMLHttpRequest {readyState: 4, ……} 當readyState==4的時候表明這個請求完成
- POST請求
// 創建一個ajax請求對象 var r = new XMLHttpRequest() // 注冊響應函數 r.onreadystatechange = () => { if(r.readyState === 4){ console.log('start begin ',r) } } //設置發送的數據的格式 r.setRequestHeader('Content-Type','application/json') // 設置請求方法和請求地址(open第三個參數代表是否使用異步) r.open('POST','#signin',true) var form = { userName:'123', pwd:'123' } var data = JSON.stringify(form) // 發送請求 r.send(data)
- 封裝它們
var ajax = (method,path,formData,callBack,content='application/json',async=true) => { var r = new XMLHttpRequest() // 注冊響應函數 r.onreadystatechange = callBack if(method === 'POST') { // 設置發送的內容的格式 r.setRequestHeader('Content-Type',content) } else {} // 設置請求方法和請求地址(open第三個參數代表是否使用異步) r.open(method,path,async) if(method === 'GET') { // 發送請求 r.send() } else { var data = JSON.stringify(formData) r.send(data) } } // 隨手封裝
豆瓣api例子