代码笔记
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例子