gdutwyg / blog Goto Github PK
View Code? Open in Web Editor NEW使用issues记录笔记
使用issues记录笔记
function a() {
var i = 0
return function (){
console.log(i++)
}
}
var a1 = a()
var a2 =a()
a1() // 0
a1() // 1
a2() // 0
a2() // 1
跨站脚本攻击,英文全称是 Cross Site Scripting, 本来缩写是CSS,但是为了和层叠样式表(Cascading Style Sheet, CSS)有所区别,所以在安全领域叫做"XSS".
XSS攻击通常指的是通过利用网页开发时留下的漏洞,恶意攻击者往Web页面里插入恶意Script代码,当用户浏览时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的
简单举个例子:
一个网站有个评论输入框,如果插入了JavaScript代码,比如<script>alert('我是执行的代码')</script>,如果没有做xss的过滤,则这段代码会被插入到html里面并执行。
反射型XSS(经过后端,不经过数据库)
例子:用户访问一个带有XSS代码的URL请求时,服务器端接收数据后处理,然后把带有XSS代码的数据发送到浏览器,浏览器解析这段带有XSS代码的数据后,最终造成XSS漏洞
存储型XSS(经过后端,存在数据库)
嵌入到web页面的恶意HTML会被存储到应用服务器端,简而言之就是会被存储到数据库,等用户在打开页面时,会继续执行恶意代码,能够持续的攻击用户
例子:评论系统等等
核心**:不相信任何用户输入
&, <, >,`,",'
在计算机领域中,堆栈是两种数据结构,它们只能在一端(称为栈顶(top))对数据项进行插入和删除
js数据类型分为两种:
之前在微信群看到一个问题
const obj = {};
obj.a = 'abc'
console.log(obj)
为什么obj常量化后,还能增加属性?
看下这个图你就明白了(图来自隔壁王叔叔)
// a标签 如果设置了target='_blank' 尽量加上这两个属性,防止信息泄露
rel="noreferrer"
rel="noopener"
sort默认排序顺序是根据 字符串Unicode码点
排序规则:
[2, 6, 2, 9, 5, 2, 1, 8, 5, 6, 1].sort((a, b) => a - b) // [1, 1, 2, 2, 2, 5, 5, 6, 6, 8, 9]
//误区
[2, 6, 2, 9, 5, 2, 1, 8, 5].sort((a, b) => a > b) // [1, 2, 2, 2, 5, 5, 6, 8, 9]
[2, 6, 2, 9, 5, 2, 1, 8, 5, 6, 1].sort((a, b) => a > b) // [2, 1, 1, 2, 2, 5, 5, 6, 6, 8, 9]
a > b 返回值只有true(1),false(0)
而正常的返回值有三种 0,-1,1,
chrome在length小于10还是正常的,但是大于10就有问题了,如上
所以推荐 a-b(升序)/ b-a(降序)
另外对于字符串的排序
// 误区
['a','s', 'b'].sort((a, b) => a - b) // ["a", "s", "b"]
因为使用unicode 码点排序的,而且‘a’ - 'b' 字符串相减,得到的结果是NaN,相当于return NaN
// 正解 charCodeAt 得到码点值
['a','s', 'b'].sort((a, b) => a.charCodeAt() - b.charCodeAt()) // ["a", "b", "s"]
// 解2
['a','s', 'b'].sort() // 使用默认处理, 默认是根据字符串Unicode码点排序
display: flex; /* 自成一行 */
display: -webkit-flex; /* Safari */
display: inline-flex; /* 内联块级弹性伸缩盒显示,根据子元素大小自适应宽度和高度 */
注意,设为Flex布局以后,子元素的float、clear和vertical-align属性将失效。
order
定义项目的排列顺序。数值越小,排列越靠前,默认为0。
flex-grow
项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
flex-shrink
项目的缩小比例,默认为1,即如果空间不足,该项目将缩小
flex-basis
分配多余空间之前,项目占据的主轴空间,默认值为auto,即项目的本来大小
flex
flex-grow/flex-shrink/ flex-basis的简写,默认值为0 1 auto。后两个属性可选。
该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。优先使用该属性。
align-self
允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。值有auto | flex-start | flex-end | center | baseline | stretch;
Therefore flex:1 it is equivalent to flex: 1 1 0
yarn是 Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具,是为了弥补 npm 的一些缺陷而出现的
"1.0.1" // 固定安装1.0.1版本
"~1.0.1" // 安装1.0.x最新的版本
"^1.0.1" // 安装1.x.x最新的版本
速度快
安装版本统一
为了防止拉取到不同的版本,Yarn 有一个锁定文件yarn.lock文件,记录了被确切安装上的模块的版本号。
补充:目前最新的npm也会生成package-lock.json
更简洁的输出
npm 的输出信息比较冗长;Yarn 简洁,只打印出必要的信息
更好的命令语义化
yarn改变了一些npm命令的名称,比如 yarn add/remove,感觉上比 npm 原本的 install/uninstall 要更清晰
css3下 absolut布局/translate上下文垂直居中
利用css3 translateX(-50%) translateY(-50%); 把left:50%;top:50%的内容器移到正中心,因为 translateX(-50%)是相对于自身的width的一半, translateY(-50%);相对与自身的height的一半,这种方法内外容器都可以是不定的。
#example5 {
width: 400px;
height: 100px;
background: #161616;
color: #fff;
position: relative;
}
#example5 .inner{
position: absolute;
left: 50%;
top: 50%;
background: #999;
transform: translateX(-50%) translateY(-50%);
}
<div id="example5">
<div class="inner">块区域垂直居中</div>
</div>
演示链接:
http://output.jsbin.com/vurapesicu
2D Transform 兼容情况:ie9以上,ios,anroid 兼容良好
方法一 利用 line-height
实现垂直居中(最简便)
略
方法二 利用 display: table
实现垂直居中(内联元素)
#example2 {
height: 100px;
background: #161616;
color: #fff;
width: 400px;
overflow: hidden;
display: table;
}
#example2 .inner{
display: table-cell;
vertical-align: middle;
height: 50px;
background:#999;
}
<div id="example2">
<div class="inner">块区域垂直居中</div>
</div>
方法三 利用margin:auto 居中(兼容性好)
<!-- margin auto居中 -->
<style>
#expample6 {
width: 400px;
height: 100px;
background: #eee;
position: relative;
}
#expample6 .inner {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
height: 50px;
width: 70%;
background: #aaa;
color:#222;
text-align: center;
}
</style>
<div id="expample6">
<div class="inner">Content here</div>
</div>
方法四 经典 absolute 布局上下文垂直居中
#example4 {
width: 400px;
height: 100px;
background: #161616;
color: #fff;
position: relative;
}
#example4 .inner{
height: 50px;
width: 200px;
position: absolute;
left: 50%;
top: 50%;
margin-top: -25px;
margin-left: -100px;
background:#999;
}
<div id="example4">
<div class="inner">块区域垂直居中</div>
</div>
方法五 利用 Flex布局 居中(补充:兼容性差 ie10+ andriod 4.4+ ios 7+)
#expample7 {
width: 400px;
height: 100px;
background: #eee;
display: flex;
justify-content: center;
align-items: center;
}
#expample7 .inner {
height: 50px;
width: 70%;
background: #aaa;
color:#222;
}
<div id="expample7">
<div class="inner">Content here</div>
</div>
相关链接:
https://my.oschina.net/wangch5453/blog/800398
css3引入的”vw”和”vh”基于宽度/高度相对于视窗大小,”vw”=”view width”, “vh”=”view height”; 以上我们称为视窗单位允许我们更接近浏览器窗口来定义大小。视窗宽度是100vw; 视窗高度是100vh; “视区”所指为浏览器内部的可视区域大小 即window.innerWidth/window.innerHeight大小,不包含任务栏标题栏以及底部工具栏的浏览器区域大小。
vmin 和 vmax则关于视口高度和宽度两者的最小或者最大值。例如:浏览器的宽度设置为1100px,高度设置为700px, 1vmin = 7px, 1vmax = 11px。如果宽度设置为800px,高度设置为1080px, 1vmin就等于8px, 1vmax则为10.8px。
1.画出宽和高自适应相等的正方形或圆
例子: http://output.jsbin.com/weroxapuva
div {
width:30%;
height:30vw;
background:green;
text-align:center;
}
其他解决方法:平时画圆或正方形是垂直方向的padding撑开容器 或者设置width 等于height;
.placeholder {
width: 20%;
padding-bottom: 20%;
background:green;
height: 0; /*防止填充内容后会出现问题*/
}
例子:http://output.jsbin.com/dikayitopa
相关介绍链接:
http://www.cocoachina.com/webapp/20150807/12940.html
http://www.zhangxinxu.com/wordpress/2012/09/new-viewport-relative-units-vw-vh-vm-vmin/
使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象(可以是import进来的单文件组件,也是对象)
// 创建构造器
// return Function
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
// data 必须是函数
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')
当需要用import去使用.vue文件时,需要保证import之后使用Vue.extend(),才能使用new 实例化, 否则new 会报错
// 注册组件,传入一个扩展过的构造器
Vue.component('my-component', Vue.extend({ /* ... */ }))
// 注册组件,传入一个选项对象 (自动调用 **Vue.extend)
Vue.component('my-component', { /* ... */ })
// 获取注册的组件 (始终返回构造器)
var MyComponent = Vue.component('my-component')
var MyComponent = Vue.extend({
template: '<div>Hello!</div>'
})
// 创建并挂载到 #app (会替换 #app)
new MyComponent().$mount('#app')
// 同上
new MyComponent({ el: '#app' })
// 或者,在文档之外渲染并且随后挂载
var component = new MyComponent().$mount()
document.getElementById('app').appendChild(component.$el)
new Vue({
el: '#app',
components: { App },
template: '<App>',
router,
store
})
请问此处的template的用处是什么?
答: 模板将会 替换 挂载的元素。挂载元素的内容都将被忽略,除非模板(App.vue)的内容有分发插槽
也就是说:template: '<App/>' 表示用<app></app>替换index.html里面的<div id="app"></div>
// 约等同于 因为我的例子div#myapp是去不掉的, 上面例子 div#app是去掉的,这样写是方便理解
// index.html
<div id="myapp">
<app></app>
</div>
// main.js
new Vue({
el:'#myapp',
router,
components:{App}
})
CSRF(Cross-site request forgery)是 跨站请求伪造。XSS利用站点内的信任用户,与XSS不同,CSRF是通过伪装来自受信任用户,在受信任的网站进行请求,盗取信息。其实就是攻击者盗用了受害者的身份,以受害者的名义向网站发送恶意请求。
根据步骤,看了图,相信不难理解,就是在一个a网站里面保留了cookie或其它信息,然后访问了一些危险网站,然后被危险网站利用你的信息伪造向a网站请求。
这时我有个疑惑,cookie不是支持同源策略的吗?怎么会被冒用?
CSRF防范
Token: 在URL中保持原参数不变,新增一个参数Token。Token的值是随机的(必须使用足够安全的随机数生成算法,或者采用真随机数生成器),由服务端返回,以隐藏的形式渲染在页面上的表单中,表单提交后验证这个token。这个token第三方是获取不到的,除非...你的网站也有xss漏洞,请看这篇文章
<input type=”hidden” name=”csrf_token” value=”tokenvalue”/>
验证码:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,。因为危险网站是不知道你当前页面的验证码,厄....这个方案可以完全解决CSRF,但个人觉得在易用性方面似乎不是太好,涉及金额的交易订单都会要求这样做。
为什么很多银行等网站会要求已经登录的用户在转账时再次输入密码,现在是不是有一定道理了?
验证 Referer
对于需要防范 CSRF 的请求,我们可以通过验证 Referer 来判断该请求是否为第三方网站发起的。
在后台接收到请求的时候,可以通过请求头中的Referer请求头来判断请求来源
SameSite
可以对 Cookie 设置 SameSite 属性。该属性设置 Cookie 不随着跨域请求发送,该属性可以很大程度减少 CSRF 的攻击,但是该属性目前并不是所有浏览器都兼容。
另记:如果网站有XSS漏洞或者一些跨域漏洞,可能导致Token泄露。在XSS攻击下,读取Token值,然后再构造出一个合法的请求,可以称为:XSRF。
参考文章:
js截取字符串有以下方法,那它们有何区别呢?下面来看看
1.参数的含义不同:
substring是以两个参数中较小一个作为起始位置,较大的参数作为结束位置
'abcefg'.substring(1,2) // b
'abcefg'.substring(1,2) // bc
'abcefg'.slice(1,2) // b
'abcefg'.substring(-2) // abcefg
'abcefg'.substring(2,-2) // ab
// => 'abcefg'.substring(2, 0) =>'abcefg'.substring(0,2)
'abcefg'.substr(-2) // fg
'abcefg'.substr(2, -2) // ''
'abcefg'.slice(-2) // fg
'abcefg'.slice(2, -2) // ce
注意:IE对substr接收负值的处理有错,它会返回原始字符串。
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
async function test() {
console.log('Hello')
await sleep(1000).then((res) => console.log(111))
console.log('world!')
}
test()
现在获取后台数据的时候,既有jq封装的ajax,也有axios等等,也有原生的XMLHttpRequest,但是今天没有介绍这些,而是介绍另外一个api,fetch
fetch,说白了,就是XMLHttpRequest的一种替代方案。如果有人问你,除了XMLHttpRequest获取后台数据之外,还有没有其他的替代原生api?
这是你就可以回答,还可以使用一种解决方案--fetch。
请注意,fetch规范与jQuery.ajax()主要有两种方式的不同,牢记:
fetch可以在现代浏览器中使用,已经挂载到BOM上面,可以直接在谷歌控制台使用,如果要注意 跨域的情况, fetch返回的是一个promise
查看fetch的支持情况:fetch的支持情况
当然,如果不支持fetch也没有问题,可以使用第三方的ployfill来实现:fetch-ployfill
简单使用
// 通过fetch获取百度的错误提示页面
//
fetch('https://www.baidu.com/search/error.html') // 返回一个Promise对象
.then((res) => {
console.log(res.text()) // res.text() 是promise对象
}).then((res) => {
console.log(res)
})
fetch(url[, option])
url:
定义要获取的资源。这可能是:
option: option 可选
一个配置项对象,包括所有对请求的设置。可选的参数有:
对于请求携带的参数:
// 通过fetch获取百度的错误提示页面
fetch('https://www.baidu.com/search/error.html?a=1&b=2', { // 在URL中写上传递的参数
method: 'GET'
})
.then((res)=>{
return res.text()
})
.then((res)=>{
console.log(res)
})
// 第一种
var url = 'https://example.com/profile';
var data = {username: 'example'};
fetch(url, {
method: 'POST', // or 'PUT'
body: JSON.stringify(data), // data can be `string` or {object}!
headers: new Headers({
'Content-Type': 'application/json'
})
}).then(res => res.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', response))
// 第二种
fetch('https://www.baidu.com/search/error.html', {
method: 'POST',
body: new URLSearchParams([["foo", 1],["bar", 2]]).toString() // 这里是请求对象
})
.then((res)=>{
return res.text()
})
.then((res)=>{
console.log(res)
})
自定义请求对象:
// myRequest
var myHeaders = new Headers();
// 自定义request
var myInit = { method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default' };
var myRequest = new Request('flowers.jpg', myInit);
fetch(myRequest).then(function(response) {
return response.blob();
}).then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;
});
检测请求是否成功
// 通过response.ok 来判断
fetch('flowers.jpg').then(function(response) {
if(response.ok) {
return response.blob();
}
throw new Error('Network response was not ok.');
}).then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;
}).catch(function(error) {
console.log('There has been a problem with your fetch operation: ', error.message);
});
使用 Headers 的接口,你可以通过 Headers() 构造函数来创建一个你自己的 headers 对象。一个 headers 对象是一个简单的多名值对
myHeaders = new Headers({
"Content-Type": "text/plain",
"Content-Length": content.length.toString(),
"X-Custom-Header": "ProcessThisImmediately",
});
不管是 请求还是 响应都能够包含body对象. body也可以是以下任意类型的实例.
Body 类定义了以下方法 (这些方法都被 Request 和 Response所实现)以获取body内容. 这些方法都会返回一个被解析后的 promise对象和数据.
var form = new FormData(document.getElementById('login-form'));
fetch("/login", {
method: "POST",
body: form
})
属性
...
方法
...同 body,因为Response实现了 Body的方法
// response.blob
var myImage = document.querySelector('.my-image');
fetch('flowers.jpg').then(function(response) {
return response.blob();
}).then(function(response) {
var objectURL = URL.createObjectURL(response);
myImage.src = objectURL;
});
参考来自
运算符 | 解释说明 |
---|---|
Not(~) | 对数字求负,然后减 1, ~(-1) = 0 |
AND(&) | 2(10) & 5(101)= 0, 2(10)&3(11) =2 |
OR(|) | 2(10) & 5(101)= 7, 2(10)&3(11) =2 |
XOR(^) | 2(10) & 5(101)= 7, 2(10)&3(11) =1 |
左移<< | 2<<5 = 64,-2<<5 = -64 保留符号 |
保留符号右移>> | 64>>5 = 2, -1>> 5= -1 |
无符号右移>>> | -1>>> 5= 134217727 |
a,b 交换值
a = 1,b=2
// 解1
a^=b
b^=a
a^=b
// 解2
[b,a] = [a,b]
function binarySearch (arr, key) {
let low = 0
let high = arr.length - 1
while (low <= high) {
let mid = Math.floor((low + high) / 2)
if (key == arr[mid]) {
return mid
} else if (key < arr[mid]) {
high = mid - 1
} else {
low = mid + 1
}
}
return -1
}
binarySearch([1,3,5], 3)
目前仅支持有序数组
...待优化
HTML5 中的一些有趣的新特性:
// package.json
// 默认值 只支持最新的两个版本/ 占有率大于1%的浏览器/ ie9+
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
// 改进后
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8",
"ios 8"
]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<h3>proxy 实现双向绑定</h3>
<div id="showData"></div>
<input type="text" id="input">
<body>
<script>
const input = document.getElementById('input')
const showData = document.getElementById('showData')
// 需要代理的数据对象
const obj = {
data: 'hello world'
}
const handler = {
//监控 data变化
set(target, prop, val) {
target[prop] = val
showData.innerText = val
input.value = val
}
}
// 构造proxy
const proxy = new Proxy(obj, handler)
//初始化值
proxy.data = obj.data
// 监听input 事件
input.addEventListener('input', (e) => {
proxy.data = e.target.value
})
</script>
</body>
</html>
冒泡排序算法的运作如下:
const arr = [-4, 5, 2, 8, 23, 0, 9, 3, 5]
function bubbleSort(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1])
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
}
}
}
bubbleSort(arr)
快排:
// 解法1
const arr = [-4, 5, 2, 8, 23, 0, 9, 3, 5]
function quickSort(arr) {
if (arr.length <= 1) {return arr}
const left = []
const right = []
const middleIndex = ~~(arr.length / 2 - 1)
const middle = arr.splice(middleIndex, 1)
arr.forEach(T => T > middle ? right.push(T) : left.push(T))
return quickSort(left).concat(middle, quickSort(right))
}
quickSort(arr)
// 解法2
const arr = [8, -4, 5, 2, 23, 0, 9, 3, 5]
function quickSort(arr, left, right) {
if (left === right) return
let key = left
while (left < right) {
while (arr[right] > arr[key] && left < right) right--
[arr[left], arr[right]] = [arr[right], arr[left]]
key = right
while (arr[left] < arr[key] && left < right) left++
[arr[left], arr[right]] = [arr[right], arr[left]]
key = left
}
}
quickSort(arr, 0, arr.length - 1)
localStorage 与 sessionStorage 是html5新增的两种本地存储方式;
了解二者的特性方便在不同的场景下使用它们;
二者共同方法:
getItem, setItem,removeItem, clear
事件:
storage
用法:
// 默认是当前域名 path路径下可访问
document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";
tips: cookie中存放不敏感的数据
控制cookie的生命期,使之不会永远有效。
浏览器将CORS(Cross-origin resource sharing)请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
符合下面两种条件 即为简单请求, 不同时满足下面两个条件,就属于非简单请求。
请求方法:
HTTP的头信息不超出以下几种字段:
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(OPTIONS)。
如果预检不通过,则无需进行正式的请求了
JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
nginx 设置 cors:
Access-Control-Allow-Origin: '*' // * 或者是允许的url
Access-Control-Allow-Methods: 'put, get, post' // 允许的请求方式
Access-Control-Allow-Headers: '' // 允许的请求头
在命名规则上,构造函数一般是首字母大写,普通函数遵照小驼峰式命名法。
有一个默认的返回值,新创建的对象(实例);
当手动添加返回值后(return语句):
// 示例代码
function foo() {
// 构造函数
var f2 = new Foo2();
console.log(f2); // 复杂数据类型 {a: 3}
console.log(this); // window
return true;
}
function Foo2() {
console.log(this); // foo2对象
return {a: 3};
}
var f1 = foo();
console.log(f1); // true
function reduceArr () {
var newArr =[]
return (function (arr){
for(var i =0;i<arr.length; i++){
if(Array.isArray(arr[i])) {
arguments.callee(arr[i])
} else {
newArr.push(arr[i])
}
}
return newArr
})(arguments)
}
reduceArr([1,3,5, [7,9]]) // [1,3,5,7,9]
reduceArr([{a:1123},[{b:11},[{c:11},{d:111}]]]) // [{a:1123}, {b: 11}, {c:11},{d:111}]
// 更优解,更少的代码
var convert = function(arr) {
var newArr = [];
arr.forEach(function(val) {
if (val instanceof Array) {
Array.prototype.push.apply(newArr, convert(val));
} else {
newArr.push(val);
}
});
return newArr;
};
convert([1,3,5, [7,9]]) // [1,3,5,7,9]
convert([{a:1123},[{b:11},[{c:11},{d:111}]]]) // [{a:1123}, {b: 11}, {c:11},{d:111}]
这里主要是使用了递归, 如果子是数组则继续调用自己
补充:如果子元素都是简单类型,则可以使用下面方法,缺点是变成字符串数字了
var c=[1,3,4,5,[6,[0,1,5],9],[2,5,[1,5]],[5]];
var b = c.toString().split(',')
// 或者
var d = c.join(',').split(',')
如果仅仅是二维数组
var arr=[[{a:123}],[{b:123},4],{c:111}];
console.log([].concat.apply([],arr))
glob是node模块, 用来匹配文件路径的,比如lib/**/*.js
, 匹配 lib 目录下所有的 js 文件
// async, 根据正则去匹配
glob(pattern, [options], cb)
- pattern {String} Pattern to be matched
- options {Object}
- cb {Function}
-err {Error | null}
-matches {Array<String>} filenames found matching the pattern
// sync
glob.sync(pattern, [options])
- pattern {String} Pattern to be matched
- options {Object}
- return: {Array<String>} filenames found matching the pattern
...
// example
var glob = require('glob')
glob.sync('./index.js') // 匹配到返回数组
fs-extra 是基于node 原生fs模块扩展过来,多了很多方法,并且返回是promise。
fs-extra adds file system methods that aren't included in the native fs module and adds promise support to the fs methods.
It also uses graceful-fs to prevent EMFILE errors. It should be a drop in replacement for fs.
var fs = require('fs')
// error
var stat = await fs.stat('./index.js')
var fs = require('fs-extra')
// success return promise
var stat = await fs.stat('./index.js')
// promise 与 await 使用, catch 捕获err
// 第一种
function a () {
return new Promise((resolve, reject) => {
// resolve('success')
reject('fail')
})
}
async function b () {
var status = await a()
console.log(status)
}
b().catch((err) => {
console.log('err', err)
})
// promise 与 await 使用, catch 捕获err
// 第二种
function a () {
return new Promise((resolve, reject) => {
// resolve('success')
reject('fail')
})
}
async function b () {
var status = await a().catch((err) => {
console.log('err', err)
})
console.log(status)
}
em:
rem:
目前有这么一个提案: 增加修饰器(Decorator)函数,用来修改类的行为
@decorator
class A {}
// 等同于
class A {}
A = decorator(A) || A;
// 例子
@testable
class MyTestableClass {
// ...
}
function testable(target) {
target.isTestable = true;
}
MyTestableClass.isTestable // true
// 修饰器不仅可以修饰类,还可以修饰类的属性。
// 例子
// 不可枚举
class Person {
@nonenumerable
get kidCount() { return this.children.length; }
}
function nonenumerable(target, name, descriptor) {
descriptor.enumerable = false;
return descriptor;
}
修饰器不能用于函数, 因为存在函数提升
Number({}) // NaN 等同于Number("[object Object]")
因为你传参是一个对象,它属于复合数据类型,会隐式调用valueOf方法。
1.隐式转换过程中,valueOf如果能返回基本数据类型则不会往下计算;
2.valueOf如果不能返回基本数据类型则会继续调用toString方法,toString方法如果还不能自动转换为基本数据类型则报错!
<div>
<span>123</span>
<span>123</span>
</div>
解决方法:
选其一即可
解决:
pkill -f SCIM.app
今天恰好需要搭一个文件上传服务器,去测试前端文件上传能否成功,这里想到使用node去解决,现在把过程记录下来。
首先编写前端页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<input type="file" name="file">
<script type="text/javascript">
// 监听change事件
$('input[type="file"]').on('change', function (e) {
var file = this.files[0];
var formData = new FormData();
formData.append('file',file);
// 使用ajax上传
$.ajax({
url: '/upload',
type: 'post',
data: formData,
cache: false, //上传文件不需要缓存
contentType: false,
processData: false //data值是FormData对象,不需要对数据做处理
}).done(function (res) {
console.log(res) // 成功打印出来res
}).fail(function (code, msg) {
console.log('upload failed please try later ', code, msg)
})
})
</script>
</body>
</html>
使用express 搭建服务器
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html') // sendFile 需要使用绝对地址
})
// 监听
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
multer做上传
// 方法1
var express = require('express')
var multer = require('multer')
var upload = multer({ dest: 'files/' }) // 设置上传文件存储的目录
var app = express()
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html') // sendFile 需要使用绝对地址
})
// 监听/upload,
// upload.single('file') 接受一个以 fieldname 命名的文件。这个文件的信息保存在 req.file
// 此处的fieldname 为前端formData.append进去的file值
app.post('/upload', upload.single('file'), function (req, res) {
res.json(req.file)
})
// 监听
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
// 方法2
var express = require('express')
var multer = require('multer')
//
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'files/') // 设置上传文件存储的目录
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now()) // 对文件重新命名,防止文件名冲突
}
})
var upload = multer({
storage
})
var app = express()
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html') // sendFile 需要使用绝对地址
})
// 监听/upload,
// upload.single('file') 接受一个以 fieldname 命名的文件。这个文件的信息保存在 req.file
// 此处的fieldname 为前端formData.append进去的file值
app.post('/upload', upload.single('file'), function (req, res) {
res.json(req.file)
})
// 监听
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
node main
完
参考:
multer
// 数组
var [a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]
// 对象
var {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40};
console.log(a); // 10
console.log(b); // 20
console.log(rest); // {c:30, d:40}
Unicode是国际组织制定的可以容纳世界上 所有文字和符号的字符编码方案,它为每种语言中的每个字符设定了统一并且唯一的编码。
表示一个Unicode的字符时,通常会用“U+”然后紧接着一组十六进制的数字来表示这一个字符。比如: U+4E25,U+1F600, U+1F601
那unicode和UTF-8有何区别?
通俗点就是
字符集:为每一个「字符」分配一个唯一的 ID(学名为码位 / 码点 / Code Point)
编码规则:将「码点」转换为字节序列的规则
编码:
1.字符串形式
javaScript 允许采用 \uxxxx形式表示一个字符,其中xxxx表示字符的 Unicode 码点。仅限于码点在 \u0000~\uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表示。
"\u0061" // 'a'
// es6表示法(支持超过0xFFFF的数值)
"\u{1F601}"
es5: String.fromCharCode(Unicode) (局限于Unicode 码点不大于0xFFFF)
String.fromCharCode(65) //return "A"
es6: String.fromCodePoint(Unicode) (支持Unicode 码点大于0xFFFF)
String.fromCodePoint('0x1F601') // "😁"
String.fromCodePoint('128513') // "😁"
解码
es5: str.charCodeAt() (局限于Unicode 码点不大于0xFFFF)
var str = 'ABC'
str.charCodeAt(0) // 65
es6: str.codePointAt() (支持Unicode 码点大于0xFFFF)
var str = "😁"
str.codePointAt(0) // 128513 10进制
str.codePointAt(0).toString(16) // "1f601" 16进制
emoji 也是一个Unicode字符。2010年,Unicode 开始为 Emoji 分配码点。
比如:U+1F4C5,U+1F468, U+1F600等
Unicode 只是规定了 Emoji 的码点和含义,并没有规定它的样式。举例来说,码点U+1F600表示一张微笑的脸,但是这张脸长什么样,则由各个系统自己实现。
如果用户的系统没有实现这个Emoji符号,用户就会看到一个没有内容的方框,因为系统无法渲染这个码点。
截至目前,共有2789个emoji字符;
参考链接:emoji-text
Unicode 允许多个码点组合表示一个 Emoji。
通过 零宽度连接符U+200D实现。
U+1F468:男人
U+1F469:女人
U+1F467:女孩
比如U+1F468 U+200D U+1F469 U+200D U+1F467,就会显示为一个 Emoji 👨👩👧
如果用户的系统不支持这种方法,就还是显示为三个独立的 Emoji 👨👩👧
零宽连字符(zero-width-joiner,ZWJ)是一个不打印字符,放在某些需要复杂排版语言(如阿拉伯语、印地语)的两个字符之间。
零宽连字符使得这两个本不会发生连字的字符产生了连字效果。零宽连字符的Unicode码位是U+200D
// 多码点转成emoji组合
function unifiedToNative(unified) {
var unicodes = unified.split('-'),
codePoints = unicodes.map((u) => `0x${u}`)
return String.fromCodePoint(...codePoints)
}
// 多组合emoji 转成码点
var s = '👩❤️👩';
for (let ch of s) {
console.log(ch.codePointAt(0).toString(16)); // 1f469 200d 2764 fe0f 200d 1f469
}
参考资料:
防抖(debounce):设定一个时间间隔,当某个频繁触发的函数执行一次后,在这个时间间隔内不会再次被触发,如果在此期间尝试触发这个函数,则时间间隔会重新开始计算
应用场景:
1.给按钮加函数防抖防止表单多次提交
2.文本输入的验证
function debounce(func, delay) {
return function(args) {
var _this = this
var _args = args
clearTimeout(func.id)
func.id = setTimeout(function() {
func.call(_this, _args)
}, delay)
}
}
节流(throttle):设定一个时间间隔,某个频繁触发的函数,在这个时间间隔内只会执行一次。也就是说,这个频繁触发的函数会以一个固定的周期执行。
应用场景:
1.DOM 元素的拖拽功能实现(mousemove)
2.监听滚动事件判断是否到页面底部自动加载更多()
3.射击游戏的 mousedown/keydown 事件
4.计算鼠标移动的距离(mousemove)
function throttle(func, delay) {
let flag = true // 第一次是否立即执行,不用等待延迟
return function() {
var _this = this
var _args = arguments
if(flag) {
func.apply(_this, _args)
return flag = false
}
// 如果有func.id说明上一次还没执行完,不往下执行
if(func.id) return false
func.id = setTimeout(function() {
clearTimeout(func.id)
// clearTimeout后还要销毁变量
func.id = null
func.apply(_this, _args)
}, delay)
}
}
参考有来自
function sum (...args) {
let sum = 0
args.forEach(v => {
v =parseFloat(v) === parseFloat(v) ? parseFloat(v) : 0
const decimalPlace = v.toString().split('.')[1]
decimalLen = decimalPlace ? decimalPlace.length : 0
len = Math.pow(10,decimalLen)
sum = ( sum * len + v* len )/ len
})
return sum
}
// 这里涉及到NaN 不等于NaN
// js精度问题(通过取小数点最长位数的精度 ,乘以10的精度次方,做完加减乘除后再除以它)
逗号操作符 :对它的每个操作数求值(从左到右),并返回最后一个操作数的值
a = 111
var obj = {
a: 123,
b: function (){
return this.a
}
}
obj.b() // 123
(c = obj.b)() // 111
(null, obj.b)() // 111 逗号运算符
(false || obj.b)() // 111
大家都知道promise是解决回调地狱的,具体的介绍文章可以看
promise-感性认知
es6-promise
这里不做过多介绍
// 简单例子
function test (ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, '完成')
})
}
test(1000).then((res) => {
console.log(res)
})
// tips:如果promise中不调用resolve 则then函数则不会继续执行
// 如果想配合await 和async一起使用, 怎么做?
function test (ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, '完成')
})
}
async function a() {
console.log('start')
await test(1000)
console.log('end')
}
a() // 你会看到先打印start => 执行setTimeout =>打印end
function test (ms) {
return new Promise((resolve, reject) => {
setTimeout(function (args){console.log(args)}, ms, 'await')
})
}
async function a() {
console.log('start')
await test(1000)
console.log('end')
}
a() // end 不会打印
// tips:如果await 与promise 一起使用, promise 里 需要执行resolve end才能打印
但是有个问题下面这个例子却不是按照 start => await => end 这样的顺序来打印的?
为什么?
// 正常的
async function a() {
console.log('start')
function aa(){console.log('await')}
await aa()
console.log('end')
}
a() // start => await => end
// 顺序不对的
async function a() {
console.log('start')
await setTimeout(function (){console.log('await')})
console.log('end')
}
a() // start => end => await
据网上的大佬说:setTimeout被放到队列里面了,所以导致这样的问题,如果是其它的普通函数就没有这个问题
柯里化: 能够把本来接受 n 个参数的函数A,转换成只接收一个参数的函数B
// 简单demo
var adder = function (x, y) {
return x + y
}
// 简单的柯里化
var adder = function(num) {
var n = num; // 对应的为参数4
return function(y) {
return n + y; // y为6 返回 4+6
}
}
adder(4)(6) // 10
// 解法1
var str ="123adsfsfaaaaaadfdfasdfaaaaeeeeeeeeeeee"
function mountMostStrNum (str) {
var obj ={}
var arr = []
for(var i = 0; i< str.length;i++) {
if(obj[str[i]]) obj[str[i]]++
else obj[str[i]] = 1
}
const Max = Math.max.apply(null, Object.values(obj))
for (prop in obj) {
if(obj[prop] === Max) arr.push({num:obj[prop],key:prop})
}
return arr
}
mountMostStrNum(str)
// 解法2
var str ="123adsfsfaaaaaadfdfeasdfabacada"
function fn(str) {
// 重新排序
str = str.split('').sort().join('')
var num = 0;
var newStr = ''
// \1 为获取第一个匹配的内容 \2 为第二个,以此类推
str.replace(/(\w)\1*/g, function ($0,$1){
if($0.length > num){
num = $0.length
newStr = $1
}
})
console.log(num + '-' + newStr)
}
fn(str)
今天在做移动端蒙层的时候遇到了子元素继承父元素的透明度(opacity)的情况
问题重现:
.opacity {
background: #000;
opacity: 0.7
}
这种写法就算给子元素opacity_child重新赋值opacity: 1
;他也同样会继承父元素opacity的值。
正确写法:
.opacity {
background: rgba(0,0,0, .7);
}
标识符 | 说明 |
---|---|
. |
匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“(.|\n)”的模式。 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。例如,“er\b”可以匹配“never”中 的“er”,但不能匹配“verb”中的“er”。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v] |
[^] | 匹配任何 不 在指定范围内的任意字符 |
(?:pattern) | 匹配pattern但不获取匹配结果, 与(pattern)相反 |
(?=pattern) | 正向肯定预查,非获取匹配,abc(?=123)/能匹配“abc123”中的“abc”,但不能匹配“abc124”中的“abc”,预查不消耗字符 |
g修饰符用语规定正则表达式执行全局匹配,也就是在找到**第一个匹配之后仍然会继续查找**
m修饰符的作用是修改^和$在正则表达式中的作用,让它们分别表示行首和行尾。
var regA = /c$/
var regB = /c$/m
console.log(`c\n asd`.match(regA)) // undefined
console.log(`c\n asd`.match(regB)) // ['c']
var regA = /abc(123)/
var regB = /abc(?:123)/
console.log('abc123'.match(regA)) // ["abc123", "123"]
console.log('abc123'.match(regB)) // ["abc123"]
var regA = /abc(?=123)/
var regB = /abc(?=123)123/
console.log('abc123'.match(regA)) // ["abc"]
console.log('abc123'.match(regB)) // ["abc123"]
var regA = /abc(?:123)/
var regB = /abc(?=123)/
console.log('abc123'.match(regA)) // ["abc123"] ,匹配括号的123,但是不获取匹配结果
console.log('abc123'.match(regB)) // ["abc"],连123都不匹配,只匹配abc
未完待续。。。
# 普通的递归
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
解决递归调用栈溢出的方法是通过尾递归优化
# 改造成尾递归
# 尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式,通过参数来处理
def fact(n):
return fact_iter(n, 1)
def fact_iter(num, product):
if num == 1:
return product
return fact_iter(num - 1, num * product)
动态语言,又称解释型语言,由解释器翻译为可以运行的机器语言。无需编译,无中间产物。这类语言包括 JavaScript,Python,php等,它们都有对应的解释器;
静态语言,又称编译型语言,需要先编译为中间产物,这类语言包括go,c/c++等
java 属于半编译型半解释型,它既有编译型语言的特点,又有解释型语言的特点
总的来说,如今编译型语言、解释性语言的分界线不再那么明显,应该避免把语言简单归类为“编译型”和“解释型”。目前这样子区分只是让自己好理解
css
css3
今天遇见一个问题: div包着一张img图片,div的高度与img的高度不相等,div底部多出空白间隙,寻找答案良久,把自己的解决方案mark一下:
解决方案
以上四种方法选其一即可
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.