Giter Site home page Giter Site logo

blog's People

Contributors

gdutwyg avatar

Watchers

 avatar  avatar

Forkers

hansummer

blog's 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

前端安全之XSS

前端安全之XSS

XSS

跨站脚本攻击,英文全称是 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会被存储到应用服务器端,简而言之就是会被存储到数据库,等用户在打开页面时,会继续执行恶意代码,能够持续的攻击用户
    例子:评论系统等等

XSS预防:

核心**:不相信任何用户输入

  • 对输入内容进行特殊字符转义,比如 &, <, >,`,",'
  • 开启 HTTPOnly cookie,让浏览器接触不到 cookie
  • 只允许用户输入我们期望的数据。比如数字等

堆栈的认识

堆栈

在计算机领域中,堆栈是两种数据结构,它们只能在一端(称为栈顶(top))对数据项进行插入和删除

  • 堆:先进先出,由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等
  • 栈:先进后出,动态分配的空间 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收

js中的堆栈

js数据类型分为两种:

  • 基本类型:UndefinedNullBooleanNumberString,属于值传递,存放在 栈(stack)内存中的简单数据段,数据大小确定,内存空间大小可以分配
  • 引用类型:即存放在 堆(heap)内存中的对象,大小不定也不会自动释放,变量实际保存的是一个指针,这个指针指向堆内存。

之前在微信群看到一个问题

const obj = {};
obj.a = 'abc'
console.log(obj)

为什么obj常量化后,还能增加属性?
看下这个图你就明白了(图来自隔壁王叔叔)

image

sort 排序

sort排序

sort默认排序顺序是根据 字符串Unicode码点

排序规则:

  • 若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
  • 若 a 等于 b,a, b位置不变,则返回 0。
  • 若 a 大于 b,排序后的数组中 a 应该出现在 b 之后, 则返回一个大于 0 的值。
[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码点排序

flex布局的属性

display: flex;  /* 自成一行 */
display: -webkit-flex; /* Safari */
display: inline-flex;  /* 内联块级弹性伸缩盒显示,根据子元素大小自适应宽度和高度 */

注意,设为Flex布局以后,子元素的float、clear和vertical-align属性将失效。

容器的属性

  • flex-direction
    flex-direction属性决定主轴的方向(即项目的排列方向)值有row(默认值) | row-reverse | column | column-reverse;
  • flex-wrap
    如果一条轴线排不下,如何换行。值有nowrap(默认值) | wrap| wrap-reverse
  • flex-flow
    是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。
  • justify-content
    主轴上的对齐方式,值有flex-start(默认值) | flex-end | center | space-between | space-around;
  • align-items
    交叉轴上如何对齐,值有flex-start | flex-end | center | baseline | stretch(默认值,项目未设置高度或设为auto,将占满整个容器的高度);
  • align-content
    多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。值有flex-start | flex-end | center | space-between | space-around | stretch(默认值,占满整个交叉轴);

项目的属性

  • 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

菜鸟教程
flex设置成1和auto有什么区别

yarn与npm

yarn 与 npm的比较

yarn是 Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具,是为了弥补 npm 的一些缺陷而出现的

  • npm安装慢,当然可以通过切换淘宝源来安装
  • 版本可能是不一致的,这就会导致同一个项目我安装的版本跟你安装的版本可能是不一致的
"1.0.1"  // 固定安装1.0.1版本
"~1.0.1" // 安装1.0.x最新的版本
"^1.0.1" // 安装1.x.x最新的版本

Yarn的优势

  • 速度快

    • 并行安装: 。npm 是按照队列执行每个 package, yarn是同步执行所有任务
    • 离线模式: 如果之前已经安装过一个软件包,用Yarn再次安装时之间从缓存中获取,就不用像npm那样再从网络下载了
  • 安装版本统一
    为了防止拉取到不同的版本,Yarn 有一个锁定文件yarn.lock文件,记录了被确切安装上的模块的版本号。

    补充:目前最新的npm也会生成package-lock.json

  • 更简洁的输出
    npm 的输出信息比较冗长;Yarn 简洁,只打印出必要的信息

  • 更好的命令语义化
    yarn改变了一些npm命令的名称,比如 yarn add/remove,感觉上比 npm 原本的 install/uninstall 要更清晰

垂直居中实现方式总结和css3单位vw-vh的简单应用

垂直居中实现的几种方式

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 兼容良好
image

其他垂直居中方法: 演示链接http://output.jsbin.com/fenecalobo

方法一 利用 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

vh, vw, vmin,vmax

简介:

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;
}

兼容情况:Android 4.4+ ios 6+
image

其他解决方法:平时画圆或正方形是垂直方向的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一些属性的使用与解读

Vue.extend

使用基础 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

// 注册组件,传入一个扩展过的构造器
Vue.component('my-component', Vue.extend({ /* ... */ }))

// 注册组件,传入一个选项对象 (自动调用 **Vue.extend)
Vue.component('my-component', { /* ... */ })

// 获取注册的组件 (始终返回构造器)
var MyComponent = Vue.component('my-component')

$mount

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

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

前端安全之CSRF

CSRF(Cross-site request forgery)是 跨站请求伪造。XSS利用站点内的信任用户,与XSS不同,CSRF是通过伪装来自受信任用户,在受信任的网站进行请求,盗取信息。其实就是攻击者盗用了受害者的身份,以受害者的名义向网站发送恶意请求。

CSRF攻击原理:
image

根据步骤,看了图,相信不难理解,就是在一个a网站里面保留了cookie或其它信息,然后访问了一些危险网站,然后被危险网站利用你的信息伪造向a网站请求。

CSRF特点

  • 攻击一般发起在第三方网站,而不是被攻击的网站。被攻击的网站无法防止攻击发生。
  • 攻击利用受害者在被攻击网站的登录凭证(cookie等),冒充受害者提交操作;而不是直接窃取数据。
  • 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”。
  • 跨站请求可以用各种方式:图片URL、超链接、CORS、Form提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。

这时我有个疑惑,cookie不是支持同源策略的吗?怎么会被冒用?

  • 当你在任何第三方网站,向 Target Site 发送 ajax 请求(不论你使用 XMLHttpRequest 还是 Fetch),请求头都不会带上 cookie。因为这是个跨域问题,同源策略进行了限制。
  • 只有当一些“自然”的请求,比如 a 标签、img 标签(这就是 GET 型 CSRF 的攻击手段),或者表单提交,在 CSRF Site 向 Target Site 发送请求过程中,浏览器会自动带上 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

参考文章:

字符串之substring,substr,slice的区别

js截取字符串有以下方法,那它们有何区别呢?下面来看看

1.参数的含义不同:

substring(start, end)

substring是以两个参数中较小一个作为起始位置,较大的参数作为结束位置

'abcefg'.substring(1,2) // b

substr(start, len)

'abcefg'.substring(1,2) // bc

slice(start, end)

'abcefg'.slice(1,2) // b
  1. 如果参数都是负数,substring会都转为0,substr则仅仅是将第一个参数与字符串长度相加后的结果作为第一个参数,而slice会将它字符串的长度与对应的负数相加
'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接收负值的处理有错,它会返回原始字符串。

js实现sleep函数

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()

fetch的简单入门

初识fetch

现在获取后台数据的时候,既有jq封装的ajax,也有axios等等,也有原生的XMLHttpRequest,但是今天没有介绍这些,而是介绍另外一个api,fetch

fetch,说白了,就是XMLHttpRequest的一种替代方案。如果有人问你,除了XMLHttpRequest获取后台数据之外,还有没有其他的替代原生api?

这是你就可以回答,还可以使用一种解决方案--fetch。

请注意,fetch规范与jQuery.ajax()主要有两种方式的不同,牢记:

  • 当接收到一个代表错误的 HTTP 状态码时,从 fetch()返回的 Promise 不会被标记为 reject, 即使该 HTTP 响应的状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的 ok 属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。
  • 默认情况下,fetch 不会从服务端发送或接收任何 cookies, 如果站点依赖于用户 session,则会导致未经认证的请求(要发送 cookies,必须设置 credentials 选项)。

fetch用法

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 API

    fetch(url[, option])

url:

定义要获取的资源。这可能是:

  • 一个 url 字符串,包含要获取资源的 URL
  • 一个 Request 对象。

option: option 可选

一个配置项对象,包括所有对请求的设置。可选的参数有:

  • method: 请求使用的方法,如 GET、POST等。
  • headers: 请求的头信息,形式为 Headers 的对象或包含 ByteString 值的对象字面量。
  • body: 请求的 body 信息:可能是一个 Blob、BufferSource、FormDataURLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。
  • mode: 请求的模式,如 cors、 no-cors 或者 same-origin。
  • credentials: 请求的 credentials,如 omit、same-origin 或者 include。为了在当前域名内自动发送 cookie , 必须提供这个选项, 从 Chrome 50 开始, 这个属性也可以接受 FederatedCredential 实例或是一个 PasswordCredential 实例。
  • cache: 请求的 cache 模式: default 、 no-store 、 reload 、 no-cache 、 * force-cache 或者 only-if-cached 。
  • redirect: 可用的 redirect 模式: follow (自动重定向), error (如果产生重定向将自动终止并且抛出一个错误), 或者 manual (手动处理重定向). 在Chrome中,Chrome 47之前的默认值是 follow,从 Chrome 47开始是 manual。
  • referrer: 一个 USVString 可以是 no-referrer、client或一个 URL。默认是 client。
    referrerPolicy: Specifies the value of the referer HTTP header. May be one of no-referrer、 no-referrer-when-downgrade、 origin、 origin-when-cross-origin、 unsafe-url 。
  • integrity: 包括请求的 subresource integrity 值 ( 例如: sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=)。

对于请求携带的参数

  • get请求直接携带在url中类似于
// 通过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)
  })
  • post请求则在option.body中设置, 类似于
// 第一种
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 对象。一个 headers 对象是一个简单的多名值对

myHeaders = new Headers({
  "Content-Type": "text/plain",
  "Content-Length": content.length.toString(),
  "X-Custom-Header": "ProcessThisImmediately",
});

Body

不管是 请求还是 响应都能够包含body对象. body也可以是以下任意类型的实例.

  • ArrayBuffer
  • ArrayBufferView (Uint8Array and friends)
  • Blob/File
  • string
  • URLSearchParams
  • FormData

Body 类定义了以下方法 (这些方法都被 RequestResponse所实现)以获取body内容. 这些方法都会返回一个被解析后的 promise对象和数据.

  • arrayBuffer()
  • blob()
  • json()
  • text()
  • formData()
var form = new FormData(document.getElementById('login-form'));
fetch("/login", {
  method: "POST",
  body: form
})

response对象

属性

  • Response.ok 只读
    包含了一个布尔值来标示该Response成功(状态码200-299) 还是失败.
  • Response.status 只读
    包含Response的状态码 (例如, 200 成功)

...

方法

  • response.text()
    读取 Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为USVString格式的promise对象
  • response.json()
    读取 Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为JSON格式的promise对象

...同 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;
});

参考来自

js位运算符

运算符 解释说明
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 中的一些有趣的新特性

HTML5 中的一些有趣的新特性:

  • 用于绘画的 canvas 元素
  • 用于媒介回放的 video 和 audio 元素
  • 对本地离线存储的更好的支持
  • 新的特殊内容元素,比如 article、footer、header、nav、section
  • 新的表单控件,比如 calendar、date、time、email、url、search

配置vue-cli的autoprefixer支持ios8

// package.json 
// 默认值 只支持最新的两个版本/ 占有率大于1%的浏览器/ ie9+
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]
// 改进后
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8",
    "ios 8"
  ]

利用proxy实现双向绑定

<!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>

参考链接: 初探 Vue3.0 中的一大亮点——Proxy

冒泡排序和快速排序

冒泡排序算法的运作如下:

  • 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数
  • 针对所有的元素重复以上的步骤,除了最后一个
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)

快排:

  • 从数列中挑出一个元素,称为“基准”(pivot),
  • 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  • 递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。
    递归到最底部时,数列的大小是零或一,也就是已经排序好了。这个算法一定会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
//  解法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, cookie

localStoragesessionStorage 是html5新增的两种本地存储方式;
了解二者的特性方便在不同的场景下使用它们;

localStorage

  • 如果没有手动删除;则永久存储在浏览器端;
  • 只要ip 端口 协议三者同一;即可共享localStorage,即使是不同tab(同个浏览器)
  • 不同浏览器不能共享
  • 最多能存储5M

sessionStorage

  • 关闭浏览器或者关闭tab标签页 sessionStorage即被清除
  • 不同tab页sessionStorage不可共享, 除非同个tab 下iframe是同源的
  • 最多能存储5M

二者共同方法:
getItem, setItem,removeItem, clear
事件:
storage

cookie

  • 生命期为只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。 存放数据大小为4K左右 。
  • 有个数限制(各浏览器不同),一般不能超过20个。
  • 与服务器端通信:每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题

用法:

// 默认是当前域名 path路径下可访问
document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";

tips: cookie中存放不敏感的数据
控制cookie的生命期,使之不会永远有效。

从后往前插入逗号运算符

image

function addCommas(nStr) {
  nStr += '';
  x = nStr.split('.')
  x1 = x[0]
  x2 = x.length > 1 ? '.' + x[1] : ''
  //匹配
  var rgx = /(\d+)(\d{3})/
  while(rgx.test(x1)) {
   // 匹配成功赋回x1, 方便后面跳出while 循环
    x1 = x1.replace(rgx, '$1' + ',' + '$2')
  }
  // x2(小数点不处理,直接返回)
  return x1 + x2
}
addCommas('123456789123111')

跨域资源共享 CORS 与 预检

浏览器将CORS(Cross-origin resource sharing)请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
符合下面两种条件 即为简单请求, 不同时满足下面两个条件,就属于非简单请求。

请求方法:

  • get
  • post
  • head

HTTP的头信息不超出以下几种字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

非简单请求的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: '' // 允许的请求头

跨域资源共享 CORS 详解
Nginx配置跨域请求

普通函数和构造函数的区别

在命名规则上,构造函数一般是首字母大写,普通函数遵照小驼峰式命名法。

构造函数:

  1. new Fn( )
  2. 构造函数内部会创建一个新的对象,即f的实例
  3. 函数内部的this指向 新创建的f的实例
  4. 默认的返回值是f的实例

普通函数:

  1. fn( )
  2. 在调用函数的内部不会创建新的对象
  3. 函数内部的this指向调用函数的对象(如果没有对象调用,默认是window)
  4. 返回值由return语句决定

构造函数的返回值:

有一个默认的返回值,新创建的对象(实例);

当手动添加返回值后(return语句):

  1. 返回值是基本数据类型-->真正的返回值还是那个新创建的对象(实例)
  2. 返回值是复杂数据类型(对象)-->真正的返回值是复杂数据类型(对象)
// 示例代码
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模块与fs-extra模块的简单介绍

glob与fs-extra

glob

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

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

em:

  • em作为font-size的单位时,其代表父元素的字体大小
  • em作为其他属性单位(padding...)时,代表自身字体大小——MDN

rem:

  • rem作用于非根元素时,相对于根元素字体大小;
  • rem作用于根元素字体大小时,相对于其出初始字体大小——MDN

修饰器(Decorator)

目前有这么一个提案: 增加修饰器(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;
}

修饰器不能用于函数, 因为存在函数提升

valueOf与 toString

  • valueOf():返回最适合该对象类型的原始值;
  • toString(): 将该对象的原始值以字符串形式返回。这两个方法一般是交由JS去隐式调用,以满足不同的运算情况。
Number({})  // NaN   等同于Number("[object Object]")

因为你传参是一个对象,它属于复合数据类型,会隐式调用valueOf方法。
1.隐式转换过程中,valueOf如果能返回基本数据类型则不会往下计算;
2.valueOf如果不能返回基本数据类型则会继续调用toString方法,toString方法如果还不能自动转换为基本数据类型则报错!

从++[[]][+[]]+[+[]]==10?深入浅出弱类型JS的隐式转换

多个span之间的空格处理方法

<div>
 <span>123</span>
 <span>123</span>
</div>

解决方法:

  • flex 布局
  • float浮动
  • 首尾标签不要有空格
  • 父元素设置font-size: 0 ,子span设置回去
  • margin负数(不推荐)

选其一即可

mac下中文输入法输入中文不显示的问题

解决:

  • 第一种:
    终端输入 pkill -f SCIM.app
  • 第二种:
    Lanchpad-活动监视器中,点中文输入法,退出这项进程
  • 第三种:
    系统偏好设置-输入法那里,将简体输入法删掉,再重新添加
  • 第四种:
    重启大法好

ts突破点

ts 突破点

  • 接口(Interfaces)
  • 声明 (declare)
  • 类(Classes)
  • 泛型(Generics)
  • 枚举类型(Enums)

node中间件Multer之文件上传

node中间件Multer之文件上传

今天恰好需要搭一个文件上传服务器,去测试前端文件上传能否成功,这里想到使用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>

node端

使用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
  • 打开localhost:3000
  • 选择文件上传
  • 你会在files文件夹看到你上传的文件

参考:
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与emoji

简单来谈谈Unicode与emoji

什么是Unicode

Unicode是国际组织制定的可以容纳世界上 所有文字和符号的字符编码方案,它为每种语言中的每个字符设定了统一并且唯一的编码。

表示一个Unicode的字符时,通常会用“U+”然后紧接着一组十六进制的数字来表示这一个字符。比如: U+4E25,U+1F600, U+1F601

那unicode和UTF-8有何区别?
通俗点就是

  • Unicode 是「字符集」
  • UTF-8 是「编码规则」

字符集:为每一个「字符」分配一个唯一的 ID(学名为码位 / 码点 / Code Point)
编码规则:将「码点」转换为字节序列的规则

JS中如何使用Unicode

编码

1.字符串形式
javaScript 允许采用 \uxxxx形式表示一个字符,其中xxxx表示字符的 Unicode 码点。仅限于码点在 \u0000~\uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表示。

"\u0061" // 'a'

// es6表示法(支持超过0xFFFF的数值)
"\u{1F601}"
  1. js方法

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的编码

emoji 也是一个Unicode字符。2010年,Unicode 开始为 Emoji 分配码点。
比如:U+1F4C5,U+1F468, U+1F600
Unicode 只是规定了 Emoji 的码点和含义,并没有规定它的样式。举例来说,码点U+1F600表示一张微笑的脸,但是这张脸长什么样,则由各个系统自己实现。

如果用户的系统没有实现这个Emoji符号,用户就会看到一个没有内容的方框,因为系统无法渲染这个码点。

截至目前,共有2789个emoji字符;
参考链接:emoji-text

emoji组合

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)
  }
}

参考有来自

由一道题目学到的知识点

image

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与 setTimeout的混合使用

大家都知道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被放到队列里面了,所以导致这样的问题,如果是其它的普通函数就没有这个问题

margin collapse(外边距塌陷)解决方案

父子元素margin collapse(外边距塌陷)

解决的方法有三种:

  • 给父元素设置一个边框,当然可以设置边框为透明;
  • 为父元素添加padding;
  • 为父元素设置overflow:hidden;

demo地址

兄弟元素margin collapse(margin 取两者最大值)

解决方法:

  • 绝对定位元素
  • float元素
  • inline-box元素
  • 给其中一个兄弟元素增加包裹的元素,给这个包裹元素添加overflow : hidden

这些不会和垂直方向上的其他元素margin折叠–其实就是可以生成新的BFC

参考资料

柯里化

柯里化: 能够把本来接受 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

image
前端之函数柯里化Currying

由判断一个字符串中出现次数最多的字符想到的

由判断一个字符串中出现次数最多的字符想到的

// 解法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']

(pattern) 和(?:pattern)

var regA = /abc(123)/
var regB = /abc(?:123)/
console.log('abc123'.match(regA)) //  ["abc123", "123"]
console.log('abc123'.match(regB)) // ["abc123"]

(?=pattern)

var regA = /abc(?=123)/
var regB = /abc(?=123)123/
console.log('abc123'.match(regA)) // ["abc"]
console.log('abc123'.match(regB)) // ["abc123"]

(?:pattern) 与(?=pattern)

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一些新特性与旧特性

css

  • letter-space: 字符间距 word-space: 单词间距

css3

  • border-radius
  • box-shadow
  • border-image
  • text-shadow
  • word-wrap
  • linear-gradient
  • transform
  • transition
  • animation
  • 媒体查询

div里包含img底部必定多出空白的解决办法

今天遇见一个问题: div包着一张img图片,div的高度与img的高度不相等,div底部多出空白间隙,寻找答案良久,把自己的解决方案mark一下:

解决方案

  • 设置div{ font-size: 0}
  • 设置img{ display: block}
  • 设置img{ vertical-align:top}
  • div设置display: flex

以上四种方法选其一即可

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.