Git Product home page Git Product logo

hsipeng's Introduction

置顶 👍

最新 🆕

Typescripts 总结 0 💬 2021-06-29 08:22:54

🏷️ : 面试, typescript

总结TypeScript在项目开发中的应用实践体会

条件类型

type B<T> = T extends string ? '1' : '2'

const a: B<s
[更多>>>](https://github.com/hsipeng/note/issues/96)
---

#### [前端知识总结](https://github.com/hsipeng/note/issues/95) <sup>0 :speech_balloon:</sup> 	 2020-08-08 08:40:10
:label: : [面试](https://github.com/hsipeng/note/labels/%E9%9D%A2%E8%AF%95), [前端](https://github.com/hsipeng/note/labels/%E5%89%8D%E7%AB%AF), [:+1:置顶](https://github.com/hsipeng/note/labels/%3A%2B1%3A%E7%BD%AE%E9%A1%B6)
自己整理出来的针对 P6 级别的前端知识体系

欢迎批评指正

地址是➡️  [http://hsipeng.github.io/fed](http://hsipeng.github.io/fed)
[更多>>>](https://github.com/hsipeng/note/issues/95)
---

#### [Redux 实现原理](https://github.com/hsipeng/note/issues/94) <sup>0 :speech_balloon:</sup> 	 2020-05-12 16:27:43
:label: : [react](https://github.com/hsipeng/note/labels/react), [redux](https://github.com/hsipeng/note/labels/redux)
```javascript
function createStore(reducer, state = null){
    let listeners = [];
    let getState = () => state;
    let subscribe = listener =>
[更多>>>](https://github.com/hsipeng/note/issues/94)
---

#### [ssl 生成 ssl 证书](https://github.com/hsipeng/note/issues/93) <sup>0 :speech_balloon:</sup> 	 2020-05-12 15:30:58
:label: : [linux](https://github.com/hsipeng/note/labels/linux), [ssl](https://github.com/hsipeng/note/labels/ssl)
## nginx 安装

sudo apt get install nginx


nginx 配置

server { listen 80 default; server_name domain; location / {

React 单元测试 0 💬 2019-09-16 08:17:22

🏷️ : react, 单元测试, jest

为何必须做单元测试

  • 单元测试对于任何 React 项目(及其他任何项目)来说都是必须的
  • 我们需要自动化的测试套件,根本目标是支持随时随地的代码调整、持续改进,从而提升团队响应力
  • 使用 TDD 开发是得到好的单元测试的唯一途径
  • 好的单元测试具备几大特征:不关注内部实现 更多>>>

分类 🗃️

词云, 点击展开详细分类

☁️ 词云 ☁️ 点击词云展开详细分类:point_down:

👍置顶 3:newspaper: - [前端知识总结](#95) 0 💬 - [网站工具Api搜集整理](#78) 0 💬 - [Flutter 学习整理](#76) 1 💬
🖼️封面 0:newspaper:
2B青年 4:newspaper: - [初爱](#23) 0 💬 - [关山月](#22) 0 💬 - [雪中歌](#21) 0 💬 - [江上有感](#18) 0 💬
axios 1:newspaper: - [基于 Promise 的 HTTP 请求客户端,axios](#13) 0 💬
babel 1:newspaper: - [react webpack babel 三剑客错误处理](#53) 0 💬
bug 0:newspaper:
centos 1:newspaper: - [ssh 权限问题](#41) 0 💬
coffeeScript 1:newspaper: - [CoffeeScript 基础知识](#8) 0 💬
component 1:newspaper: - [## Re: Zero 学习一个组件](#43) 0 💬
css 1:newspaper: - [前端开发,从草根到英雄(总结)](#12) 0 💬
Curry 1:newspaper: - [柯里化](#29) 0 💬
D3 1:newspaper: - [D3 与 React ](#63) 0 💬
Data Analysis 1:newspaper: - [Data Analysis with Python——01](#75) 0 💬
Data Analysis with Python 9:newspaper: - [Data Analysis with Python——09](#89) 1 💬 - [Data Analysis with Python——08](#88) 0 💬 - [Data Analysis with Python——07](#87) 0 💬 - [Data Analysis with Python——06](#86) 0 💬 - [Data Analysis with Python——05](#85) 0 💬 - [Data Analysis with Python——04](#84) 0 💬 - [Data Analysis with Python——03](#83) 0 💬 - [Data Analysis with Python——02](#82) 0 💬 - [Data Analysis with Python——01](#81) 0 💬
duplicate 0:newspaper:
enhancement 0:newspaper:
ES6 3:newspaper: - [ES6 数组去重](#57) 0 💬 - [ES6 知识点整理](#34) 0 💬 - [【译】ES 6 代理 (Proxy) 简介 ](#32) 0 💬
eslint 1:newspaper: - [vscode AutoSave With Prettier ](#64) 0 💬
flutter 1:newspaper: - [Flutter 学习整理](#76) 1 💬
gh-pages 1:newspaper: - [travis ci 持续集成](#26) 0 💬
git 2:newspaper: - [travis ci 持续集成](#26) 0 💬 - [git 安装与使用](#14) 0 💬
help wanted 0:newspaper:
html 1:newspaper: - [前端开发,从草根到英雄(总结)](#12) 0 💬
invalid 0:newspaper:
java 3:newspaper: - [Oracle 与 MySql 区别(笔记)](#6) 0 💬 - [java基础知识笔记(2)](#5) 0 💬 - [java基础知识笔记(1)](#4) 0 💬
javascript 11:newspaper: - [前端常用算法梳理](#77) 0 💬 - [ES6 数组去重](#57) 0 💬 - [函数式编程](#49) 0 💬 - [javascript 转换](#38) 0 💬 - [算法](#36) 0 💬 - [this的指向](#31) 0 💬 - [闭包的应用](#30) 0 💬 - [手撸一个 redux 实现](#28) 0 💬 - [javascript 精粹](#27) 0 💬 - [基于 Promise 的 HTTP 请求客户端,axios](#13) 0 💬 - [前端开发,从草根到英雄(总结)](#12) 0 💬
jest 1:newspaper: - [React 单元测试](#92) 0 💬
jsonp 1:newspaper: - [Promise Jsonp](#50) 0 💬
koa 1:newspaper: - [Koa 中间件](#60) 0 💬
linux 2:newspaper: - [ssl 生成 ssl 证书](#93) 0 💬 - [Ubuntu安装BTSync](#7) 1 💬
MiniProgram 1:newspaper: - [小程序ios 安卓兼容性](#65) 0 💬
Mybatis 1:newspaper: - [java SSM框架的搭建](#25) 0 💬
mysql 1:newspaper: - [Mysql 备忘](#45) 0 💬
nodejs 3:newspaper: - [Promise Jsonp](#50) 0 💬 - [travis ci 持续集成](#26) 0 💬 - [基于 Promise 的 HTTP 请求客户端,axios](#13) 0 💬
npm 1:newspaper: - [publish package to npmjs.com](#66) 0 💬
NumPy 1:newspaper: - [Data Analysis with Python——01](#75) 0 💬
poem 4:newspaper: - [初爱](#23) 0 💬 - [关山月](#22) 0 💬 - [雪中歌](#21) 0 💬 - [江上有感](#18) 0 💬
prettier 1:newspaper: - [vscode AutoSave With Prettier ](#64) 0 💬
promise 1:newspaper: - [基于 Promise 的 HTTP 请求客户端,axios](#13) 0 💬
python 14:newspaper: - [Data Analysis with Python——09](#89) 1 💬 - [Data Analysis with Python——08](#88) 0 💬 - [Data Analysis with Python——07](#87) 0 💬 - [Data Analysis with Python——06](#86) 0 💬 - [Data Analysis with Python——05](#85) 0 💬 - [Data Analysis with Python——04](#84) 0 💬 - [Data Analysis with Python——03](#83) 0 💬 - [Data Analysis with Python——02](#82) 0 💬 - [Data Analysis with Python——01](#81) 0 💬 - [python数据分析之性能度量](#80) 0 💬 - [python数据分析之数据缺失](#79) 0 💬 - [Data Analysis with Python——01](#75) 0 💬 - [python 环境](#74) 0 💬 - [python之pyenv版本控制](#15) 0 💬
question 0:newspaper:
Raspberry Pi 0:newspaper:
Re: Zero 2:newspaper: - [Re: Zero JSX 回调函数中的 this](#44) 0 💬 - [## Re: Zero 学习一个组件](#43) 0 💬
react 14:newspaper: - [Redux 实现原理](#94) 0 💬 - [React 单元测试](#92) 0 💬 - [D3 与 React ](#63) 0 💬 - [React 单元测试](#62) 0 💬 - [React 服务端渲染](#61) 0 💬 - [redux 写法详解](#59) 0 💬 - [react webpack babel 三剑客错误处理](#53) 0 💬 - [一个可用于生产环境的开发框架的搭建](#48) 0 💬 - [项目结构详解](#47) 0 💬 - [Re: Zero JSX 回调函数中的 this](#44) 0 💬 - [## Re: Zero 学习一个组件](#43) 0 💬 - [无状态函数式组件](#37) 0 💬 - [面试纪要](#33) 0 💬 - [手撸一个 redux 实现](#28) 0 💬
redux 3:newspaper: - [Redux 实现原理](#94) 0 💬 - [redux 写法详解](#59) 0 💬 - [手撸一个 redux 实现](#28) 0 💬
Spring 1:newspaper: - [java SSM框架的搭建](#25) 0 💬
SpringMVC 1:newspaper: - [java SSM框架的搭建](#25) 0 💬
ssh 1:newspaper: - [ssh 权限问题](#41) 0 💬
ssl 1:newspaper: - [ssl 生成 ssl 证书](#93) 0 💬
SSM 1:newspaper: - [java SSM框架的搭建](#25) 0 💬
ssr 1:newspaper: - [React 服务端渲染](#61) 0 💬
this 1:newspaper: - [this的指向](#31) 0 💬
Travis CI 1:newspaper: - [travis ci 持续集成](#26) 0 💬
typescript 2:newspaper: - [Typescripts 总结](#96) 0 💬 - [vue with typescript](#73) 0 💬
ubuntu 2:newspaper: - [Ubuntu使用dnsmasq作本地DNS缓存](#24) 0 💬 - [Ubuntu安装BTSync](#7) 1 💬
vscode 1:newspaper: - [vscode AutoSave With Prettier ](#64) 0 💬
vue 2:newspaper: - [vue with typescript](#73) 0 💬 - [vue全面介绍--全家桶(vue笔记一)](#10) 0 💬
Webpack 10:newspaper: - [webpack to umd package](#72) 0 💬 - [webpack 4 - webpack-merge to config dev prod environment quickly](#71) 0 💬 - [webpack4-HMR with webpack-dev-server](#70) 0 💬 - [webpack4-Atuo serve dist file](#69) 0 💬 - [# webpack4-command line without config file](#68) 0 💬 - [webpack4 - Basic config](#67) 0 💬 - [react webpack babel 三剑客错误处理](#53) 0 💬 - [webpack 3.5.5 文档 再读](#52) 0 💬 - [webpack 4 ](#39) 0 💬 - [Webpack 入门](#11) 0 💬
wechat 1:newspaper: - [小程序ios 安卓兼容性](#65) 0 💬
wontfix 0:newspaper:
函数式编程 1:newspaper: - [函数式编程](#49) 0 💬
前端 3:newspaper: - [前端知识总结](#95) 0 💬 - [前端常用算法梳理](#77) 0 💬 - [柯里化](#29) 0 💬
单元测试 2:newspaper: - [React 单元测试](#92) 0 💬 - [React 单元测试](#62) 0 💬
取整 1:newspaper: - [javascript 转换](#38) 0 💬
学习笔记 1:newspaper: - [javascript 精粹](#27) 0 💬
小程序 3:newspaper: - [小程序热区](#58) 0 💬 - [小程序组件及组件事件转发](#56) 0 💬 - [小程序热区](#55) 0 💬
开源 0:newspaper:
技术 0:newspaper:
数据分析 13:newspaper: - [如何炼就数据分析的思维?](#91) 0 💬 - [数据分析惯用的5种思维方法](#90) 0 💬 - [Data Analysis with Python——09](#89) 1 💬 - [Data Analysis with Python——08](#88) 0 💬 - [Data Analysis with Python——07](#87) 0 💬 - [Data Analysis with Python——06](#86) 0 💬 - [Data Analysis with Python——05](#85) 0 💬 - [Data Analysis with Python——04](#84) 0 💬 - [Data Analysis with Python——03](#83) 0 💬 - [Data Analysis with Python——02](#82) 0 💬 - [Data Analysis with Python——01](#81) 0 💬 - [python数据分析之性能度量](#80) 0 💬 - [python数据分析之数据缺失](#79) 0 💬
数据缺失 1:newspaper: - [python数据分析之数据缺失](#79) 0 💬
文艺 4:newspaper: - [初爱](#23) 0 💬 - [关山月](#22) 0 💬 - [雪中歌](#21) 0 💬 - [江上有感](#18) 0 💬
新生 1:newspaper: - [拿到公司电脑,之后要做些什么](#46) 0 💬
无状态组件 1:newspaper: - [无状态函数式组件](#37) 0 💬
日记 6:newspaper: - [对未来的思考](#20) 0 💬 - [谁说的青春无悔](#19) 0 💬 - [生活,需要一些仪式感 ](#17) 0 💬 - [2015-09-08-反思](#16) 0 💬 - [2017-05-19-总结](#3) 0 💬 - [热爱工作热爱生活](#2) 0 💬
柯里 1:newspaper: - [柯里化](#29) 0 💬
框架 1:newspaper: - [一个可用于生产环境的开发框架的搭建](#48) 0 💬
热区 1:newspaper: - [小程序热区](#55) 0 💬
电影 2:newspaper: - [无问西东](#51) 0 💬 - [姜文的一步之遥](#9) 0 💬
知识点 1:newspaper: - [ES6 知识点整理](#34) 0 💬
算法 2:newspaper: - [前端常用算法梳理](#77) 0 💬 - [算法](#36) 0 💬
翻译 1:newspaper: - [【译】ES 6 代理 (Proxy) 简介 ](#32) 0 💬
读书笔记 1:newspaper: - [生活,需要一些仪式感 ](#17) 0 💬
闭包 1:newspaper: - [闭包的应用](#30) 0 💬
面试 5:newspaper: - [Typescripts 总结](#96) 0 💬 - [前端知识总结](#95) 0 💬 - [面试纪要](#33) 0 💬 - [this的指向](#31) 0 💬 - [柯里化](#29) 0 💬
音乐 0:newspaper:
项目 1:newspaper: - [项目结构详解](#47) 0 💬

hsipeng's People

Contributors

hsipeng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

whkendny

hsipeng's Issues

手撸一个 redux 实现

手写redux

首先需要讲一些概念。

  • 纯函数

一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用,我们就把这个函数叫做纯函数。
特点:

  1. 函数的返回结果只依赖于它的参数。
  2. 函数执行过程里面没有副作用。
  • React.js 特性 —— context

组件间 共享状态 属性
只能传入子组件
父组件不能读取该属性

  • 高阶组件

高阶组件是一个函数(而不是组件),它接受一个组件作为参数,返回一个新的组件

  • 共享结构的对象

就是类似把 obj 所有的属性都复制到 obj2 里面,相当于对象的浅复制,obj 里面的内容和 obj2 是完全一样的,但是却是两个不同的对象。除了浅复制对象,还可以覆盖、拓展对象属性
例: const obj = { a: 1, b: 2} const obj2 = { ...obj, b: 3, c: 4} // => { a: 1, b: 3, c: 4 },覆盖了 b,新增了 c

简介

在一个正常的 react app中需要 组件 也需要组件间交互的数据的store。在这个app中我们用provider 容器包裹 组件,用context 中包围store, 在组件间共享。每个组件都做纯组件化,不包含逻辑,只根据props 渲染。 这就是redux 的设计模式。

套路就是

// 定一个 reducer
function reducer (state, action) {
  /* 初始化 state 和 switch case */
}

// 生成 store
const store = createStore(reducer)

// 监听数据变化重新渲染页面
store.subscribe(() => renderApp(store.getState()))

// 首次渲染页面
renderApp(store.getState()) 

// 后面可以随意 dispatch 了,页面自动更新
store.dispatch(...)

组件

组件就不多说了,主要 Smart 组件 vs Dumb 组件。

Dumb 组件 不包含所有逻辑
Smart 组件包含逻辑和从context 中获取相应的数据

store

它接受的参数叫 reducer,reducer 是一个函数, 而且是纯函数(Pure Function)

function createStore (reducer) {
  let state = null
  const listeners = []
  // 观察着模式 发布和订阅
  // 根据数据是否更新重新渲染相应的足迹
  const subscribe = (listener) => listeners.push(listener)
  const getState = () => state
  const dispatch = (action) => {
    state = reducer(state, action)
    listeners.forEach((listener) => listener())
  }
  dispatch({}) // 初始化 state
  return { getState, dispatch, subscribe }
}

reducer

reducer接受两个参数,一个是 state,一个是 action。
如果没有传入 state 或者 state 是 null,那么它就会返回一个初始化的数据。如果有传入 state 的话,就会根据 action 来“修改“数据,但其实它没有、也规定不能修改 state,而是要通过上节所说的把修改路径的对象都复制一遍,然后产生一个新的对象返回。如果它不能识别你的 action,它就不会产生新的数据,而是(在 default 内部)把 state 原封不动地返回。

reducer 是不允许有副作用的。你不能在里面操作 DOM,也不能发 Ajax 请求,更不能直接修改 state,它要做的仅仅是 —— 初始化和计算新的 state。

function themeReducer (state, action) {
  if (!state) return {
    themeName: 'Red Theme',
    themeColor: 'red'
  }
  switch (action.type) {
    case 'UPATE_THEME_NAME':
      return { ...state, themeName: action.themeName }
    case 'UPATE_THEME_COLOR':
      return { ...state, themeColor: action.themeColor }
    default:
      return state
  }
}

const store = createStore(themeReducer)
...

Github
部分代码
react-redux.js

import React, { Component } from 'react'
import PropTypes from 'prop-types'

export const connect = (mapStateToProps, mapDispatchToProps) => (WrappedComponent) => {
  class Connect extends Component {
    static contextTypes = {
      store: PropTypes.object
    }

    constructor () {
      super()
      this.state = {
        allProps: {}
      }
    }

    componentWillMount () {
      const { store } = this.context
      this._updateProps()
      store.subscribe(() => this._updateProps())
    }

    _updateProps () {
      const { store } = this.context
      let stateProps = mapStateToProps
        ? mapStateToProps(store.getState(), this.props)
        : {} // 防止 mapStateToProps 没有传入
      let dispatchProps = mapDispatchToProps
        ? mapDispatchToProps(store.dispatch, this.props)
        : {} // 防止 mapDispatchToProps 没有传入
      this.setState({
        allProps: {
          ...stateProps,
          ...dispatchProps,
          ...this.props
        }
      })
    }

    render () {
      return <WrappedComponent {...this.state.allProps} />
    }
  }
  return Connect
}


export class Provider extends Component {
  static propTypes = {
    store: PropTypes.object,
    children: PropTypes.any
  }

  static childContextTypes = {
    store: PropTypes.object
  }

  getChildContext () {
    return {
      store: this.props.store
    }
  }

  render () {
    return (
      <div>{this.props.children}</div>
    )
  }
}

index.js

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import ReactDOM from 'react-dom'
import Header from './Header'
import Content from './Content'
import './index.css'

import { Provider } from './react-redux'

function createStore (reducer) {
  let state = null
  const listeners = []
  const subscribe = (listener) => listeners.push(listener)
  const getState = () => state
  const dispatch = (action) => {
    state = reducer(state, action)
    listeners.forEach((listener) => listener())
  }
  dispatch({}) // 初始化 state
  return { getState, dispatch, subscribe }
}

const themeReducer = (state, action) => {
  if (!state) return {
    themeColor: 'red'
  }
  switch (action.type) {
    case 'CHANGE_COLOR':
      return { ...state, themeColor: action.themeColor }
    default:
      return state
  }
}

const store = createStore(themeReducer)


// 删除 Index 里面所有关于 context 的代码
class Index extends Component {
  render () {
    return (
      <div>
        <Header />
        <Content />
      </div>
    )
  }
}

// 把 Provider 作为组件树的根节点
ReactDOM.render(
  <Provider store={store}>
    <Index />
  </Provider>,
  document.getElementById('root')
)

雪中歌

雪一场,梦呓回,听歌几时,欲听还休,欲听还休,再从头,列表循环,又一年,
人在,情在,有歌有诗,有美酒,一切都是最好的安排。

2016-01-14

Re: Zero JSX 回调函数中的 this

#this #React #bind

类(React.Component 构造的组件)的方法默认是不会绑定 this 的。

一共有三种方法解决

  • bind 方法
class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}
  • 属性初始化器语法
class LoggingButton extends React.Component {
  // This syntax ensures `this` is bound within handleClick.
  // Warning: this is *experimental* syntax.
  handleClick = () => {
    console.log('this is:', this);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}
  • 回调函数中使用 箭头函数
class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // This syntax ensures `this` is bound within handleClick
    return (
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
    );
  }
}

注意点

传递参数

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

参数 e 作为 React 事件对象将会被作为第二个参数进行传递。通过箭头函数的方式,事件对象必须显式的进行传递,但是通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递。

class Popper extends React.Component{
    constructor(){
        super();
        this.state = {name:'Hello world!'};
    }
    
    preventPop(name, e){    //事件对象e要放在最后
        e.preventDefault();
        alert(name);
    }
    
    render(){
        return (
            <div>
                <p>hello</p>
                {/* Pass params via bind() method. */}
                <a href="https://reactjs.org" onClick={this.preventPop.bind(this,this.state.name)}>Click</a>
            </div>
        );
    }
}

vue全面介绍--全家桶(vue笔记一)

简介

“简单却不失优雅,小巧而不乏大匠”。
Vue.js 是一个JavaScriptMVVM库,是一套构建用户界面的渐进式框架。它是以数据驱动和组件化的**构建的,采用自底向上增量开发的设计。相比于Angular.js,Vue.js提供了更加简洁、更易于理解的API,使得我们能够快速地上手并使用Vue.js;同时比起 React + Redux 相对复杂的架构,Vue.js 更加轻量级也更加容易上手,是初创项目的首选前端框架。Vue 的核心库只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合。并且作者是华人的关系,Vue拥有着对华人开发者最友好的api文档和官方教程。

vue、React、Angular1对比

在Angular1中,在scope作用域中每一次数据变化,会触发watcher的重新计算,angular对常用的dom事件,xhr事件等做了封装, 在里面触发进入angular的digest流程。在digest流程里面,会从rootscope开始遍历, 检查所有的watcher。并且,如果一些 watcher 触发另一个更新,脏检查循环(digest cycle)可能要运行多次。Vue则没有这个问题,因为它使用基于依赖追踪的观察系统并且异步队列更新,数据的变化都是独立处罚的,除非数据之间有明确的依赖关系。
vue官方宣称vue的渲染性能优于react。为了有理有据让人信服,vue开发团队建立了一个简单的对比性能的项目(https://github.com/chrisvfritz/vue-render-performance-comparisons),它负责渲染10000个列表项100次。Vue官方将每一个参照项目都分别运行 20 次并取最好的结果结果如下图:

由此可见,Vue的性能是远好于Angular1,并且稍微优于React的。

社区拓展对比

Angular1的背后是Google,所以社区基础是不需要担心的,从Tutorial到StackOverflow的问题数量都可以反映出生态系统很完整。Vue和React都有强大的社区支持。React有状态管理库Flux、ReduxVue,相应的,Vue有vuex。Vue 和 React 都提供了强大的路由库来应对大型应用。然而Vue的路由库和状态管理库都是由官方维护支持的。React 则是选择把这些问题交给社区维护,因此创建了一个更分散的生态系统。但相对的,React 的生态系统相比 Vue 更加繁荣。此外,Vue 提供了Vue-cli 脚手架,包括了Webpack,Browserify,甚至路由库,能让你非常容易地构建项目。

学习陡峭度对比

在指令与组件方面,Vue中将指令和组件分得更清晰。指令只封装 DOM 操作,而组件代表一个自给自足的独立单元,有自己的视图和数据逻辑。在 Angular1 中两者有不少相混的地方。在API与框架设计方面,angular1都比vue要复杂的多。就个人感觉而言,angular1和React的学习曲线会相对陡峭一些,而vue的编码方式会更趋近于前端开发者的编程习惯。
因为vue的作者是**人,vue的官方网站、教程和api肯定是最完善、最易懂的。此外,每次大版本的发布,都会伴随着详尽的迁移说明文档,包含了很多详尽的阐述以及许多迁移的例子,甚至还有迁移工具。

vue的缺点

Vue就这么好,难道没有缺点吗?当然有,vue虽然在16年非常火爆,但是相比于angular和react,不论是成熟度还是社区活跃度都还不是对手。此外,Vue明确声明了自己放弃了对IE8的支持。再看看现在的招聘网站上,有多少写了需要有angular经验,而又有多少写了需要vue经验,就可见vue的影响力相比于angular和react还差的很远。

vue全家桶及项目架构

Vue有著名的全家桶系列,包含了vue-router(http://router.vuejs.org),vuex(http://vuex.vuejs.org), vue-resource(https://github.com/pagekit/vue-resource)。再加上构建工具vue-cli,就是一个完整的vue项目的核心构成。

vue-router路由

推荐使用npm工具来安装vue-router
npm install vue-router
通过import导入并定义Vue模块、vue-router模块和需要使用的组件,在本例中,分别是Goods、Ratings和Seller组件。最后,如果在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装路由功能。
import Vue from’vue’
importRouter from’vue-router’

import Goods from ‘@/components/goods/goods’;
import Ratings from ‘@/components/ratings/ratings’;
import Seller from ‘@/components/seller/seller’;

Vue.use(Router); // 需要import Vue和Router,不然会报错undefined
通过const router= new VueRouter()来定义一个路由,并传入对应的配置,包括路径path和组件components。

vuex状态管理

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。如前面所提到的,Vuex 已经集成到 Vue 的官方调试工具vue Devtools,可以轻松的查看项目中的Vuex状态变化情况。
假设有这样一个场景:我们的项目规模比较大,有多个父组件,每个父组件同时又包含多个子组件。如何保持对所有时间的追踪将变得很困难。到底哪个事件是哪个组件派发的,哪个组件该监听哪个事件?父组件将变得和子组件耦合越来越严重,因为它需要明确的派发和监听子组件的某些事件。项目逻辑分散在各个组件当中,很容易导致逻辑的混乱,不利于我们项目的维护。
这就是 Vuex 用来解决的问题。 Vuex 的四个核心概念分别是:
The state tree:Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。至此它便作为一个『唯一数据源(SSOT)』而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
Getters:用来从 store 获取 Vue 组件数据。
Mutators:事件处理器用来驱动状态的变化。
Actions:可以给组件使用的函数,以此用来驱动事件处理器 mutations
Vuex和简单的全局对象是不同的,当Vuex从store中读取状态值的时候,若状态发生了变化,那么相应的组件也会高效的更新。并且,改变store中状态的唯一途径就是提交commit mutations。这样便于我们跟踪每一次状态的变化。只要发生了状态的变化,一定伴随着mutation的提交。

vue-resource介绍

Vue-resource有体积小,支持IE9以上的浏览器,支持promise特性的特点。同样推荐使用npm来安装Vue-resource。
$ npm install vue-resource
在安装并引入vue-resource后,可以基于全局的Vue对象使用http,也可以基于某个Vue实例使用http。
在发送请求后,使用then方法来处理响应结果,then方法有两个参数,第一个参数是响应成功时的回调函数,第二个参数是响应失败时的回调函数。
vue-resource的请求API是按照REST风格设计的,它提供了7种请求API:
· get(url,[options])
· head(url,[options])
· delete(url,[options])
· jsonp(url,[options])
· post(url,[body], [options])
· put(url, [body],[options])
· patch(url,[body], [options])

vue工程目录结构

components/文件夹用来存放Vue 组件。个人建议,把每一个组件中使用到的image图片放置到对应的组件子文件目录下,便于统一的管理
Node_modules/npm安装的该项目的依赖库
vuex/文件夹存放的是和 Vuex store 相关的东西(state对象,actions,mutations)
router/文件夹存放的是跟vue-router相关的路由配置项
build/文件是 webpack 的打包编译配置文件
static/文件夹存放一些静态的、较少变动的image或者css文件
config/文件夹存放的是一些配置项,比如服务器访问的端口配置等
dist/该文件夹一开始是不存在,在我们的项目经过 build 之后才会产出
App.vue根组件,所有的子组件都将在这里被引用
index.html整个项目的入口文件,将会引用我们的根组件 App.vue
main.js入口文件的 js 逻辑,在webpack 打包之后将被注入到 index.html 中

Vue核心功能

计算属性

假设有如下的购物车结算场景,用户选中商品的总金额是根据商品数量、选中商品种类数
和商品单价来变化的。然而,数量、选中种类数量和单价这几个对象都是根据用户选择而动态变化的,如果在前端模版中为了计算最终商品总额,放入这几个动态变化的变量(商品数量、商品单价、选中商品种类),会让这个逻辑变得复杂难以维护。在这种情况下,模版便不再简洁清晰。Vue给出了此种场景的解决方案,在任何复杂的逻辑,vue都推荐使用计算属性。

computed vs method

也许会有疑问,这个计算属性和定义一个method方法不是差不多么?这两者最大的区别是计算属性是基于它的依赖进行缓存的。计算属性只有在它的相关依赖发生变化时才会重新计算求值。在本例中,只有当选择商品的价格price和数量count发生变化时,这个计算属性totalPrice才会重新计算新的值。这就意味着,只要totalPrice这个值没有发生变化,多次访问该计算属性会立即返回之前的计算结果,而不必再次执行计算。

模版语法

Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。Vue的模版语法包括了使用双大括号插入文本、使用v-html插入纯HTML内容、使用v-bind插入对象、类似angular的v-if、v-show、v-for指令、以及过滤器等等。

组件化

组件(Component)是 Vue.js 最强大的功能。组件可以封装可重用的代码,通过传入对象的不同,实现组件的复用。
举一个简单的组建例子,我们首先编写一个star组件,它就是一个普通的star.vue文件。它的作用就是简单实现了一个五角星。
如何在其他的vue文件中使用这个star组件呢?如下图所示,首先通过import引入star组件对象,并在想使用star组件的vue文件中声明注册star组件。现在就可以愉快的通过标签来在该vue文件中任意地方使用star组件了。在你想展示一个五角星的地方,使用一个star标签,就可以轻松完成这个功能。
组件实例的作用域是孤立的。这意味着不能在子组件的模板内直接引用父组件的数据。要让子组件使用父组件的数据,我们需要通过子组件的props选项。如本例所示,子组件star要显式的使用props选项声明它期待获得的数据。在这里就是指的“size”和“score”两个变量。我们可以通过父级给子组件star传入大小和数值这两个对象,来实现对子组件的定制化。

过渡效果

Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果,可以用简单的几行代码实现酷炫的过渡效果。Vue 提供了 transition 的封装组件,在使用v-if、v-show等方法使得transition内部dom元素发生变化时,可以给任何元素和组件添加 entering/leaving 过渡。
当v-show中内容发生变化时,transition组件中的元素会发生状态的改变,在应用了transition封装后,Vue会自动识别目标元素是否应用了CSS过渡效果动画,如果有,会在合适的时机添加 entering/leaving的class来实现该过渡效果。
下图所示是一个简单的过渡效果的例子,需要将想实现过渡效果的元素放在transition标签中包裹,通过name=“slide-fade”来声明过渡效果名称,并在对应的vue文件中添加过渡效果
的css样式,这样就可以简单的完成该元素的过渡效果。

总结

根据不完全统计,包括饿了么、稀土掘金、苏宁易购、美团、天猫、荔枝FM、房多多、Laravel、htmlBurger等国内外知名大公司都在使用vue进行新项目的开发和旧项目的前端重构工作。
此外,vue + vuex+ vue-resource + vue-router + webpack + es6 + less的项目架构成为了越来越多大公司的第一选择。

java SSM框架的搭建

目录结构:

├─src
│  │  applicationContext.xml
│  │  jdbc.properties
│  │  springmvc.xml
│  │  sqlMapConfig.xml
│  │  
│  ├─controller
│  │      UserController.java
│  │      
│  ├─mapper
│  │      UserMapper.java
│  │      
│  ├─pojo
│  │      User.java
│  │      UserMapper.xml
│  │      
│  └─service
│          UserService.java
│          UserServiceImpl.java
│          
└─WebContent
    │  index.jsp
    │  
    ├─META-INF
    │      MANIFEST.MF
    │      
    └─WEB-INF
        │  userList.jsp
        │  web.xml
        │  
        └─lib
                aopalliance-1.0.jar
                asm-3.3.1.jar
                c3p0-0.9.0.jar
                cglib-2.2.2.jar
                com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
                commons-fileupload-1.2.2.jar
                commons-io-2.0.1.jar
                commons-logging-1.1.1.jar
                ehcache-core-2.6.5.jar
                javassist-3.17.1-GA.jar
                jstl-1.2.jar
                junit-4.9.jar
                log4j-1.2.17.jar
                mybatis-3.2.2.jar
                mybatis-ehcache-1.0.2.jar
                mybatis-spring-1.2.0.jar
                mysql-connector-java-5.1.28-bin.jar
                ojdbc6-11.1.0.7.0.jar
                slf4j-api-1.7.5.jar
                slf4j-log4j12-1.7.5.jar
                spring-aop-3.2.3.RELEASE.jar
                spring-aspects-3.2.3.RELEASE.jar
                spring-beans-3.2.3.RELEASE.jar
                spring-context-3.2.3.RELEASE.jar
                spring-context-support-3.2.3.RELEASE.jar
                spring-core-3.2.3.RELEASE.jar
                spring-expression-3.2.3.RELEASE.jar
                spring-jdbc-3.2.3.RELEASE.jar
                spring-test-3.2.3.RELEASE.jar
                spring-tx-3.2.3.RELEASE.jar
                spring-web-3.2.3.RELEASE.jar
                spring-webmvc-3.2.3.RELEASE.jar

主要配置文件为:

  • sqlMapConfig.xml mybatis配置
  • springmvc.xml springMVC配置
  • applicationContext.xml spring容器配置
  • jdbc.properties 数据相关配置

当然为了调试方便,可以加入log4j配置,输出debug信息
log4j.properties

log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

java基础知识笔记(1)

首先确定以下概念:

  • 对象:对象是一个类的实例
  • :类是一个模块,它描述一类对象的行为和状态
  • 方法:方法就是行为,逻辑运算,数据修改,所有动作都是在方法中完成的
  • 实例变量:每个对象都有独特的实例变量,用于保存对象的状态。

类型变量

  • 局部变量 : 声明和初始化都在方法中
  • 成员变量: 定义在类中,方法体外
  • 类变量: static 修饰

数据类型

  • 内置数据类型:

    • byte(-2^7 ~ 2^7-1)
    • short(-2^15 ~ 2^15-1)
    • int(-2^31 ~ 2^31-1)
    • log(-2^63 ~ 2^63-1)
    • float(0.0f 32位)
    • double(0.0d 64位)
    • boolean
    • char(\u0000 ~ \uffff)
  • 引用类型:

    引用类型指向一个对象,指向对象的变量就是引用变量。如site

    Site site = new Site("http://lirawx.cn");
    

自动类型转换

  • 转换顺序
byte,short,char -> int -> long -> float -> double
  1. 不能对boolean转换
  2. 不能把对象转成不相关的类
  3. 容量大的转换成小的,转换过程总会溢出或损失精度
    int i = 128;
    byte b = (byte)i;
    byte最大127,会溢出
  4. 浮点数到整数,会舍弃小数,不是简单的四舍五入
    (int)12.7 == 12
    (int)-25.89f == -45

修饰符

访问修饰符

当前类 同一包内 子孙类 其他内
public 可以访问 可以访问 可以访问 可以访问
protected 可以访问 可以访问 可以访问 -
default 可以访问 可以访问 - -
private 可以访问 - - -

不使用任何关键字:对同一包内可见,接口变量隐式的声明为 public static final,接口里的方法默认情况访问权限为public。

非访问修饰符

  • static:独立于对象的静态变量,类变量,切静态变量只有一份拷贝
  • final:修饰的类不能继承,修饰的方法不能被继承类重新定义,变量不可修改
  • abstract:创建抽象类和抽象方法
  • synchronized/volatile: 用于线程
  • transient : 修饰短暂属性

对未来的思考

怪我多喝一包咖啡,到现在都没有睡着,想了很多,很少有这时候独自思考这么多了,或许不曾孤独如此良久。我再想以后我到底会怎么样,有什么爱好,有什么工作,又怎么样过好自己的生活,说不定单身一直,也说不定已经携伊人的手了。仔细的回想了以前的以前,久到小学可能,一直喜欢笛子啊,之类的,特别中意武侠,手持一支笛子,背负一把长剑,帅气。可能是自己身为**人深深的继承了**古老的传统也不一定。或许我以后应该学着吹下笛子,小时候直到现在都不知道自己喜欢什么,会做什么,很多都是凭感觉,觉得挺好就挺好,太过随意了现在觉得。太过飘忽不定,我觉得起码现在我应该要确定以及肯定一下自己以后的发展道路了。
或许是分手之后长长的空虚寂寞区间,让我也反思了许多。身在21世纪,我却许多次想摆脱这个浮华的世纪带快我的脚步,拒绝微信,拒绝qq,拒绝淘宝之类过激的举动,现在一一妥协,慢慢融入自己的生活,当然问题当然不是变与不变,与加速度一样,身在这个社会怎么可能逃过物理法则。我想说的是这些过快的浮华和过多的诱惑导致我如今不知道该如何是好,一路走来,磕磕绊绊,迷雾重重,会掩盖本来的面目。想来我已经谈了三次主要的恋爱,第一次记住了一个名字,第二次记住了一个qq号,第三次记住了一个电话号码,三次都不能释怀,三次让我也成长了不少。曾经看过读者,记得有一篇文章写,幸福需要等,不要急着去寻找。三次我都以为是上天给我的暗示,我成功的把握住了,期间我也体会到了什么事爱,爱一个人的感觉无论隔着多远,多久,心总是充满热量,激动愉悦,面对所爱的人,那一刻你觉得世界那么美好,美好到今生只为遇见你。然而第二个女友问我:当激情褪去,你还会爱她么?我竟然无言以对,或许只是头脑里激素的一阵悸动,分泌失调。我这样逃避自己和她。我意识到自己善变到了精神都不正常的地步,经常强迫自己还有别人跟自己头脑里的印象重合,每个人都必须和自己投影是一致的,不一致要修正,感觉自己就是上帝一样,谁都是有罪的,都必须向自己赎罪。所以我要告诉自己要保持谦卑,要保持好奇心,要懂得尊敬,要保持希望,要永远乐观,还要一直学习新的东西,最后最重要的要坚持下去。
我觉得父母给我最好的教育就是没有限制我的可能性,我也表现的很懂事,当然现在远在家外,我也很少联系他们,但是我知道我是爱他们的,家庭给我最大的最好的就是要读书,我一直保持着对读书的渴望,不读书总会有一种莫名的愧疚感。我觉得这一生都无法改变这一习惯。这一切都来自我的家庭教育。上高中之前可以说是为父母他们读书,那么上大学必须要为自己读书了,大一我确定是为自己读书,尝试了很多不同的东西,然而还是被自己的原则全都否决了,退掉所有社团,推掉所有的责任,一个人独自的玩耍,导致大二被大学上了一年。大三我觉得我要吧大学上一遍才行。
我想了想自己的计划,我想看书时必要的,其次还得练字,行书吧,楷书已经不适合我了。保留自己文艺气息,保持自己的审美。大学毕业不要马上工作,我想去外面走走,见见除开景区以外的世界。比如**,比如苏州,比如日本。可以打工换食宿在国内,其他的就只能攒钱了。我想以后要开一家不一样的书店,可以加上现代的科技,互联网之类的元素。先想到这里吧。

2015-10-25

git 安装与使用

###一、git基本环境配置

1.首先去www.github.com上注册帐号

2.本机安装git. sudo apt-get install git

3.给本机注册SSH,请移步https://help.github.com/articles/generating-ssh-keys,注册SSH后就默认可以在本机上传代码之类,不用在输入用户名密码...

4.配置Git的配置文件,username和email
git config --global user.name "your name" //配置用户名
git config --global user.email "your email" //配置email
配置这个每次commit都会通过email去关联github账户

###二、git基本命令

1.git clone 命令将远程的Git版本库在本地克隆一份,然后就可以用git对该目录下的文件进行版本控制。并且此时会默认生成一个文件夹,文件夹名字是远程仓库名字,cd进去之后,git remote -v发现存在远程仓库,其地址是clone的地址,名字是orgin。
比如 (git clone git://github.com/1292765944/ACM.git) 或者 (git clone [email protected]:1292765944/ACM.git)但不要用https协议

2.git init 你可以在本地创建了一个工作目录,然后进入这个目录,使用'git init'命令进行初始化,那么git以后就会对该目录下的文件进行版本控制。

这个命令应用比较简单,先cd到目标文件夹,然后git init即可。

3.git remote 通过这个命令我们可以建立和远程仓库的联系。

比如 git remote add origin [email protected]:1292765944/ACM.git 我们就把[email protected]:1292765944/ACM.git这个远程仓库取了origin别名,以后我们再访问的时候可以直接使用别名。

git remote -v 查看远程仓库

git remote rm [name] 删除远程仓库

git pull [remoteName] [localBranchName]拉取远程仓库。比如git pull origin master

git push [remoteName] [localBranchName]更新远程仓库,注意在更新之前要先pul。比如git push origin master

4.git add 该命令当前更改或者新增的文件加入到本地仓库中 git add 后面可以加文件名/目录,还有一中写法git add .会自动判断添加哪些文件然后把这个添加提交到本地的仓库

5.git rm 该命令删除本地仓库中的一些文件。git rm 后面可以直接接文件名,但要删除目录时,要加-r

6.git commit 提交你之前做的rm和add操作并必须要提交附加信息。比如 git commit -m "acm_template"

###三、使用git从本地上传github举例

第一步: 进入要所要上传文件的目录输入命令 “git init”
第二步: 创建一个远程仓库origin,使用命令 “git remote add origin [email protected]:1292765944/ACM.git”,其中1292765944是你的GitHub的用户名,ACM是你要上传到GitHub的仓库
第三步:比如你要添加一个文件xxx到本地仓库,使用命令 “git add xxx”,可以使用“git add .”自动判断添加哪些文件,然后把这个添加提交到本地的仓库,使用命令 ”git commit -m ”说明这次的提交“,最后把本地仓库origin提交到远程的GitHub仓库,使用命令 ”git push origin master“

【译】ES 6 代理 (Proxy) 简介


ES 6 代理 (Proxy) 简介

代理 (Proxy) 对象是ES 6 中的新特性之一。 代理对象是为了方便开发者自定义一些基本操作 (如 查询属性、 赋值、 枚举、 执行方法等 ) 而定义的。

在进行下面讲解之前,你可能会觉得一些名词/理论很陌生,我建议你先看看下面的介绍,之后你就会发现
代理 (Proxy) 原理实际上很简单很实用。

三个名词定义如下:

  • handler ---- 用来包含(traps) 的模版对象
  • traps ---- 提供来访问代理对象属性的一些方法
  • target ---- 代理对象虚拟化的对象

你可以在这里查看完整的traps 方法列表。

下面我们来看看一些例子和实际应用。

语法

下面是一个 Proxy 语法使用的例子。 在这里我们传入了两个参数,一个target (目标对象,这里我们传入了一个空对象), 一个handler (一个模版对象)。

Proxy 语法

普通对象访问自身属性

普通对象访问自身属性
上面的代码片段,我们创建了一个对象包含了两个属性( reason 和 code)。 我们可以看到在控制台的第 7 行 和第 8 行显示出了对应的值。然后在第 9 行 , 当我们尝试访问一个不存在的属性时 (bear) , 返回了一个undefined。

代理对象访问属性

代理对象访问属性

看起来比上面的普通对象代码要多一些,我们来分析下代码。 我们用 GET trap 构建了一个模版对象(line 3) , 模版对象( handler ) 将目标对象和请求的属性名传递给 trap 。在第 11 行 我们创建了和上面普通对象的例子。我们的代理 (Proxy ) 在第 16 行 实现。

和上面普通对象访问自身属性一样,在 18 行 和 19 行 同样返回的相同的值。但是在 20 行 控制台输出了 -
“ key does not exist (属性不存在)”。

我们已经实现了在自定义的代理对象 ( Proxy ) 中覆盖默认的方法。

通过代理强制进行属性值的格式校验

通过代理强制进行属性值的格式校验

在这个代码片段中我们在第 4 行定义了我们的模版对象 (handler) ,之后我们先确保 age 属性已经被定义赋值,之后我们再检查值的类型和范围大小是不是符合要求。我们还定义了验证不通过的自定义错误信息。最后, 在 16 行我们设置了一个新的属性值,之后控制台返回了一个成功的信息,以上就是属性校验的内容。

以下是一些 Proxy 的实际应用

  • 验证
  • 属性值的过滤
  • 属性访问插件
  • 追踪属性访问记录
  • 可撤销的应用
  • 在 javascript 中实现 DOM

可视化(G2、D3)

G2

官网

核心

创建图表

2.0 与3.0 的区别, id 与container
backgroud、 padding 等常用属性

装载数据

支持的数据格式

  • JSON 数组
    集合数据类型

  • DataView 对象 ➡️

Guide 辅助元素

图标上添加额外的标识。

travis ci 持续集成

事故起因

我想再github pages 上发布hexo博客.然后自己又很懒,不想每次都再hexo -g; hexo -d等命令.然后又想再issues上写博客,真的很方便.虽然别人可以自由无线评论,但是世界本来就是开放的,这样也无可厚非.

实现原理

travis 可以又nodejs的环境.所有我就打算用nodejs脚本,根据github的api,获取到issues.然后手动下载到./source/_posts目录下.然后通过一系列命令,发布到gh-pages上.

具体实现

下载issues的主要js代码.

request(options, function (error, response, body) {
    if (!error && response.statusCode == 200) {
        var data = JSON.parse(body);
        for (iss in data){
            if(data[iss].state=='open'){

                var article = '';
                article+='---\n';
                article+='layout: post\n';
                article+='tags: '+getTags(data[iss].labels)+'\n';
                article+='title: '+data[iss].title+'\n';
                article+='date: '+data[iss].created_at+'\n';
                article+='---\n\n';
                article+=data[iss].body;
                var fN = getFileName(data[iss].created_at,data[iss].title);
                var filePath =calFilePath(data[iss].created_at,fN);
                if(!fsExistsSync(filePath)){

                   mkdirsSync(filePath);
                    var out = fs.createWriteStream(filePath+fN,{encoding:'utf-8','flag': 'a'});
                    out.write(article);
                    out.end();
                    console.log(fN+'----- 已经写入');
                }else if(!fsExistsSync(filePath+fN)){
                    var outs = fs.createWriteStream(filePath+fN,{encoding:'utf-8','flag': 'a'});
                    outs.write(article);
                    outs.end();
                    console.log(fN+'----- 已经写入');
                }else{
                    console.log(fN+'----- 已经存在');
                }


        }
        }
    }
});



其中request的option 如下

var options = {
    url: 'https://api.github.com/repos/lirawx/mirror/issues',
    headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36',
        'Host':'api.github.com',
        'DNT':'1',
        'If-None-Match':'W/"074817d16634c58050520f5c85690abf"',
        'Upgrade-Insecure-Requests':'1',
        'Cache-Control':'0'
    }
};

可以参考,具体请前往https://developer.github.com/v3/repos/

travis ci 配置文件

language: node_js
node_js: stable

# S: Build Lifecycle
install:
  - npm install


#before_script:
 # - npm install -g gulp
#node genmd.js

script:
  - node genmd.js
  - hexo g

after_script:
  - cd ./public
  - git init
  - git config user.name "xxxx"
  - git config user.email "[email protected]"
  - git add .
  - git commit -a -m "Update posts"
  - git push --force --quiet "https://${GH_TOKEN}@${GH_REF}" master:xxxxx
  - cd ..
  - git init
  - git config user.name "xxxxx"
  - git config user.email "[email protected]"
  - git add .
  - git commit -a -m "Update source"
  - git push --force --quiet "https://${GH_TOKEN}@${GH_REF}" master:xxxxx
# E: Build LifeCycle

branches:
  only:
    - xxxxx
env:
 global:
   - GH_REF: github.com/xxxx/xxxx.git

注意我是一个git仓库,两个不同的分支,一个source分支, 一个master分支,source方源代码,master放gh-pages.

算法

名词概念

  • 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面;
  • 不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;
  • 内排序:所有排序操作都在内存中完成;
  • 外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;
  • 时间复杂度: 一个算法执行所耗费的时间。
  • 空间复杂度: 运行完一个程序所需内存的大小。

排序分类:

冒泡排序

<1>.比较相邻的元素。如果第一个比第二个大,就交换它们两个;
<2>.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
<3>.针对所有的元素重复以上的步骤,除了最后一个;
<4>.重复步骤1~3,直到排序完成。

function bubbleSort(arr) {
    var len = arr.length;
    for (var i = 0; i < len; i++) {
        for (var j = 0; j < len - 1 - i; j++) {
            if (arr[j] > arr[j+1]) {        //相邻元素两两对比
                var temp = arr[j+1];        //元素交换
                arr[j+1] = arr[j];
                arr[j] = temp;
            }
        }
    }
    return arr;
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(bubbleSort(arr));//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

改进建议

  • 设置一个标志性变量, 用于记录每趟排序中最后一次进行交换的位置。
  • 每趟排序进行正向反向两次冒泡。

选择排序

<1>.初始状态:无序区为R[1..n],有序区为空;
<2>.第i趟排序(i=1,2,3...n-1)开始时,当前有序区和无序区分别为R[1..i-1]和R(i..n)。该趟排序从当前无序区中-选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[1..i]和R[i+1..n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;
<3>.n-1趟结束,数组有序化了。

function selectionSort(arr) {
    var len = arr.length;
    var minIndex, temp;
    console.time('选择排序耗时');
    for (var i = 0; i < len - 1; i++) {
        minIndex = i;
        for (var j = i + 1; j < len; j++) {
            if (arr[j] < arr[minIndex]) {     //寻找最小的数
                minIndex = j;                 //将最小数的索引保存
            }
        }
        temp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp;
    }
    console.timeEnd('选择排序耗时');
    return arr;
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(selectionSort(arr));//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

快速排序

<1>.从数列中挑出一个元素,称为 "基准"(pivot);
<2>.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
<3>.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

var quickSort2 = function(arr) {
    console.time('2.快速排序耗时');
  if (arr.length <= 1) { return arr; }
  var pivotIndex = Math.floor(arr.length / 2);
  var pivot = arr.splice(pivotIndex, 1)[0];
  var left = [];
  var right = [];
  for (var i = 0; i < arr.length; i++){
    if (arr[i] < pivot) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }
console.timeEnd('2.快速排序耗时');
  return quickSort2(left).concat([pivot], quickSort2(right));
};

var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(quickSort(arr,0,arr.length-1));//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
console.log(quickSort2(arr));//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

参考

十大经典排序算法总结(JavaScript描述) - 掘金

Promise Jsonp

promise 和 jsonp 结合

依赖包

  • fetch-jsonp
fetchJsonp(url, {
	josnpCallback: 'jsonpCallback'
})
.then(function(response){
	return response.json()
})
.then(function(json){
	console.log('success:' + json)
}).catch(function(ex){
	console.log('error:' + ex)
})
  • jsonp
jsonp(url, {
	param: 'jsonpCallback'
},function(err, data) {
	if(err){
		console.log('error')
	}else {
		console.log(data)
	}
})

2017-05-19-总结

不是你上了大学,而是你被大学上了

首先写这篇总结的原因,从5月初开始我投了大量的简历,然而其结果都是被干掉,我归结出几个原因:

  • 大学太过平庸

大学里我一直宅在宿舍里,至少是大一到到大二都是这样,自己刚刚接触到大学这个庞大的团体,每天都有新的事物吸引着我的注意力,而我始终都没有明确自己的理想与目标,我一直以为同学都差不多,其实差很多,当我在召唤师峡谷里欲仙欲死的时候有的同学在看专业书籍准备考研,有的在准备面试暑期实习生,有的甚至在看雅思,托付,等等一些高大上的书籍,准备考证。而我或者我们这一类人都嗤之以鼻,很不屑,"大学不是来玩的么",这句话高中老师肯定多对我们说过,很遗憾,我们上课知识点没记住,却记住了这个最坑爹的一句话。我只想说你玩得起吗?你爸是李刚?你家族很庞大?你已经身家过亿?

  • 缺乏自主性和计划性

大学每天除了上课,就是在宿舍上网或者打游戏,这是常态,但是我很遗憾的告诉你,人生不是这么过的,一旦你陷入了享乐主义的恶性循环你会发现你的人生一团糟。你刚刚起床,考研的同学已经吃好早饭,到自习室或者图书馆自习了,而当你在床上玩着手机,自以为生活就是该这么悠闲,大学真好玩的时候,自学做技术的人已经完成了项目的一个模块了。当你中午起床的时候,你觉得一天才刚刚开始,然后你打开电脑,发现很无聊,点开了LOL,然后和队友互怼,你觉得很生气,然后你继续下一把,发现这把还行,。。。。。。n局后,唉,怎么天都黑了,然后你继续躺上床,捧着KINDLE,装着文艺,看着玄幻爽文,我去,猪脚帅的跟我一样,放技能都是恐怖如斯!。。。。N day 过去,你混着日子过完春夏秋冬,突然就毕业了,人家要么考清华北大,而你只能家里蹲,要么就是拿到大厂的OFFER,而你却说不急,我慢慢找(找你妹啊!!)。

  • 缺乏清醒的自我认识

每个人考到大学,都觉得自己很牛逼,把电脑装饰linux,然后进入字符界面, sudo apt get install cmatrix ,运行之后,哇,这不是黑客帝国吗,我好牛逼,然后就没有然后了,一点也没有深入理解其中运行原理。这样的例子还有很多,每个人都觉得自己了不起,吧自己的身段放的老高,忘了自己应届生的身份,找工作的时候,发现好难,校招的题目都做不出来,去社招面试,结果一点项目经验都没有,over,一遍一遍始终都摆不正自己的身份,没有什么是应该的,你不会就是不会,没有什么可以狡辩的,copy再多,自己也写不出一行代码,悲哀。

  • 缺乏对职业的认识

职业是什么,说白了就是你将来用来养家糊口的工具手段,当一个人温饱都成问题的时候,哪有什么职业可言,你必须要计划自己将来5到10年你想做什么,而不是等着老师给你布置 “找工作”的作业,职业是使命,你得为之付出青春和汗水,而不能丝毫怀疑,同时你还要学习,不断的学习,职业随着时间的延长,会不断进化发展,会需要很多的技能,你没有掌握就会被时代遗弃,简单来说你会丢掉饭碗。所以你要努力的保护自己的饭碗。当然有了职业,并不是说你所有的心思都必须放在它上面,你得学会分清主次,工作的时候要认真负责,休息的时候可以和同事交流分享经验,与人相处也是职业成功的必备要素。同时你还有有减轻自己工作压力的方法,比如打篮球,钓鱼,打保龄球等等之类的休闲活动。劳逸结合才能走得更远更舒畅。

  • 学校培养人才和社会需要严重脱节

21世纪,科技发展迅速,职业素养要求越来越高,学校里的课程只能教授一些基本的知识,无法实际应用于社会生产,导致了很大一部分同学很被动,也很悲哀,被夹在当中,很无奈,没法找到理想的工作,也没有健全自己的道德素养体系,缺乏对自我的认识,没有自主性。种种原因导致了现阶段的一系列问题。

以上是个人浅见,或者说牢*,慎重翻阅!!

webpack 4

核心概念

入口(entry)

webpack.config.js

可以通过在 webpack 配置中配置 entry 属性,来指定一个入口起点(或多个入口起点)

module.exports = {
  entry: './path/to/my/entry/file.js'
};

输出(output)

output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件。你可以通过在配置中指定一个 output 字段,来配置这些处理过程

const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  }
};

loader

loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。

test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。
use 属性,表示进行转换时,应该使用哪个 loader。

  • .css 文件
// css 加载 先加载css-loader ,之后sytle-loader 插入html.
      {
        test: /\.css$/,
		// test: /\.less$/,
		// test: /\.scss$/,
        use: [
          { loader: "style-loader"},
          { loader: "css-loader"},
			// { loader: "less-loader"},
			// { loader: "less-loader"},
        ]
      }
  • .js 文件 ,一般要es6 转 es5
// ES6 转码
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-react']
          }
        }
      }
  • .png | .gif 等图片处理
// 图片加载
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: "file-loader",
            options: {}
          }
        ]
      }

插件(plugins)

loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。

想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建它的一个实例。

常用插件

  • ExtractTextWebpackPlugin

它会将所有的入口 chunk(entry chunks)中引用的 *.css,移动到独立分离的 CSS 文件。因此,你的样式将不再内嵌到 JS bundle 中,而是会放到一个单独的 CSS 文件(即 styles.css)当中。 如果你的样式文件大小较大,这会做更快提前加载,因为 CSS bundle 会跟 JS bundle 并行加载。

const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin("styles.css"),
  ]
}

开发环境建议不要拆分css文件,热更新不会生效。

  • HtmlWebpackPlugin
    该插件将为你生成一个HTML5文件,其中包括使用script标签的body中的所有webpack包。 只需添加插件到你的webpack配置如下:
var HtmlWebpackPlugin = require('html-webpack-plugin');
var path = require('path');

var webpackConfig = {
  entry: 'index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'index_bundle.js'
  },
  plugins: [new HtmlWebpackPlugin()]
};

参考资料

webpack 官网

Webpack 入门

Webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。

打包js

app/runoob1.js 文件
document.write(require("./runoob2.js"));
 webpack runoob1.js bundle.js

webpack 根据模块的依赖关系进行静态分析,这些文件(模块)会被包含到 bundle.js 文件中。Webpack 会给每个模块分配一个唯一的 id 并通过这个 id 索引和访问模块。 在页面启动时,会先执行 runoob1.js 中的代码,其它模块会在运行 require 的时候再执行。

LOADER

Webpack 本身只能处理 JavaScript 模块,如果要处理其他类型的文件,就需要使用 loader 进行转换。
所以如果我们需要在应用中添加 css 文件,就需要使用到 css-loader 和 style-loader,他们做两件不同的事情,css-loader 会遍历 CSS 文件,然后找到 url() 表达式然后处理他们,style-loader 会把原来的 CSS 代码插入页面中的一个 style 标签中。

app/runoob1.js 文件

require("!style!css!./style.css");
document.write(require("./runoob2.js"));

require CSS 文件的时候都要写 loader 前缀 !style!css!,当然我们可以根据模块类型(扩展名)来自动绑定需要的 loader。 将 runoob1.js 中的 require("!style!css!./style.css") 修改为 require("./style.css") :

app/runoob1.js 文件
require("./style.css");
document.write(require("./runoob2.js"));

然后执行:

webpack runoob1.js bundle.js --module-bind 'css=style!css'

配置文件

我们可以将一些编译选项放在配置文件中,以便于统一管理:
创建 webpack.config.js 文件,代码如下所示:

app/webpack.config.js 文件
module.exports = {
    entry: "./runoob1.js",
    output: {
        path: __dirname,
        filename: "bundle.js"
    },
    module: {
        loaders: [
            { test: /\.css$/, loader: "style!css" }
        ]
    }
};

接下来我们只需要执行 webpack 命令即可生成 bundle.js 文件。webpack 命令执行后,会默认载入当前目录的 webpack.config.js 文件。

插件

插件在 webpack 的配置信息 plugins 选项中指定,用于完成一些 loader 不能完成的工。
webpack 自带一些插件,你可以可以通过 cnpm 安装一些插件。
使用内置插件需要通过以下命令来安装:
cnpm install webpack --save-dev
比如我们可以安装内置的 BannerPlugin 插件,用于在文件头部输出一些注释信息。
修改 webpack.config.js,代码如下:

app/webpack.config.js 文件
var webpack=require('webpack');

module.exports = {
    entry: "./runoob1.js",
    output: {
        path: __dirname,
        filename: "bundle.js"
    },
    module: {
        loaders: [
            { test: /\.css$/, loader: "style!css" }
        ]
    },
    plugins:[
    new webpack.BannerPlugin('菜鸟教程 webpack 实例')
    ]
};

然后运行 webpack,打开 bundle.js,可以看到文件头部出现了我们指定的注释信息。

开发环境

当项目逐渐变大,webpack 的编译时间会变长,可以通过参数让编译的输出内容带有进度和颜色。

$webpack --progress --colors

如果不想每次修改模块后都重新编译,那么可以启动监听模式。开启监听模式后,没有变化的模块会在编译后缓存到内存中,而不会每次都被重新编译,所以监听模式的整体速度是很快的。

webpack --progress --colors --watch

当然,我们可以使用 webpack-dev-server 开发服务,这样我们就能通过 localhost:8080 启动一个 express 静态资源 web 服务器,并且会以监听模式自动运行 webpack,在浏览器打开 http://localhost:8080/http://localhost:8080/webpack-dev-server/ 可以浏览项目中的页面和编译后的资源输出,并且通过一个 socket.io 服务实时监听它们的变化并自动刷新页面。

# 安装
cnpm install webpack-dev-server -g

# 运行
webpack-dev-server --progress --colors

谁说的青春无悔

谁说的青春无悔,我怎么天天都在回望昨日一往情深,不懂什么是爱,现在已经麻木了,何人还爱,何人敢爱,又有谁来爱我。口口声声不悔不回头,渐渐的丢失了底线,然而周围已经没有了可以将心托付的人了,以前可能还有,暧昧多于友谊,然而只能是友谊,不懂为什么她答应又拒绝,或许她比我懂得多,那时我竟然不懂,不明白,原因,太多话没有说明,太多情没有诉尽,太多人还不了债。想来这便是人生?我不懂,我也不知道我怎么去选择,我想让时间划过,但我又想阻延时间,却抓不住,时间在风中溜走。或许我便是矛盾的一生,我期待一个英雄驾着云彩,携我出周身荆棘缠绕,世界一片光明。

2015-10-20

前端开发,从草根到英雄(总结)

文章信息:

原文:

作者:@Jonathan Z. White

翻译:

译者:jieniu

总结

HTML CSS基础练习

工具

练习使用html,css,包裹google字体的api和google字体的css技巧,当然还有排版。要将注意力放在html,css在一起时如何工作的。然后再dribble这个网站上寻找灵感,在codepen上编写代码。

要点

  • 语义标记
  • css命名约定
  • css重置
  • 跨浏览器支持
  • css预处理器和后处理器
  • 网格系统和响应式

最后要保持更新,从一个又一个例子中学习。

JavaScript

基本知识

语言
  • 语法和类型
  • 控制流河错误处理
  • 循环和遍历
  • 函数
交互

文档对象模型(DOM)

  • 什么是DOM?
  • 如何查询元素?
  • 如何添加事件监听者?
  • 如何合适的改变DOM节点属性?
检查

调试JavaScript

进阶知识

语言
  • 强化原型
  • 作用域
  • 闭包
  • 事件循环
  • 事件通知
  • 请求、调用和绑定
  • 回调和承诺
  • 变量及函数挂起
  • Currying
Imperative vs. Declarative

JavaScript和DOM如何交互,有两种方法:imperative和declarative,一方面,declarative程序专注于what,另一方面,imperative程序专注于how。
Jquery是imperative方法,然后才是Angular和React库declarative方法

Ajax

新的浏览器请求标准是Fetch

jQuery

jQuery不是唯一的imperative DOM操作解决方案,PlainJS和You Might Not Need jQuery是两个很好的资源,他们会告诉你和jQuery一样的频繁使用的JavaScript函数。

ES5 vs. ES6

有必要知道你今天看到的应用,要么使用ES5,要么使用ES6。ES5,ES6,ES2016,ES.Next: JavaScript版本到底怎么了和Dan Wahlins的ES6入门——下一代JavaScript是很好的ES6介绍。接着你可以在ES6功能列表查看ES5到ES6的变化。如果你还想了解更多,去Github代码库获得更多ES6功能信息。

JavaScript框架

Angular,React + Flux,Ember,Aurelia,Vue,和Meteor。你不需要学习所有的框架,选一个学习即可,不要追赶框架的潮流,取而代之的是,你需要理解框架程序底下的原则和哲学。

架构模型

MVC MVVM

与其让HTML保留应用状态,还不如用一个JavaScript对象——通常被称为Model——来存储状态。

设计模式
  • 装饰者模式
  • 工厂模式
  • 单件模式
  • Revealing module
  • 外观模式
  • 观察者模式
AngularJS

AngularJS是一个JavaScript MVC框架,有时也是一个MVVM框架,它由google维护,并在2010年初次发布时给JavaScript社区带来了一场风暴

React + Flux

Angular很好解决了程序员在构建复杂系统时所面对的问题,另一个流行的工具是React,它是一个创建用户接口的库,你可以把它想象成MVC中的V。由于React只是一个库,所以它会经常伴随着一个框架Flux

风格指南

JavaScript风格指南是一组代码规范,它会帮助你设计具有可读性和可维护性高的代码。

  • AirBnB的编码规范
  • 常用的JavaScript原则
  • Node编码规范
  • MDN编码规范
编码基础

我已经无法形容读好代码给我带来的帮助到底有多大,一旦当你想读新的好代码时,可以上Github上找

  • Lodash
  • Underscore
  • Babel
  • Ghost
  • NodeBB
  • KeystoneJS

许多时候,人在做,天在看。

CoffeeScript 基础知识

CoffeeScript 是一门编译到 JavaScript 的小巧语言. 在 Java 般笨拙的外表下, JavaScript 其实有着一颗华丽的心脏. CoffeeScript 尝试用简洁的方式展示 JavaScript 优秀的部分.

CoffeeScript 的指导原则是: "她仅仅是 JavaScript". 代码一一对应地编译到 JS, 不会在编译过程中进行解释. 已有的 JavaScript 类库可以无缝地和 CoffeeScript 搭配使用, 反之亦然. 编译后的代码是可读的, 且经过美化, 能在所有 JavaScript 环境中运行, 并且应该和对应手写的 JavaScript 一样快或者更快.


安装

CoffeeScript 编译器本身是 CoffeeScript 写的, 使用了 Jison parser generator. 命令行版本的 coffee 是一个实用的 Node.js 工具. 不过编译器并不依赖 Node, 而是能运行于任何 JavaScript 执行环境, 比如说在浏览器里(看上边的"试一试 CoffeeScript").

安装前你需要最新稳定版 Node.js, 和 npm (Node Package Manager). 借助 npm 可以安装 CoffeeScript:

npm install -g coffee-script

语言手册

一些基础, CoffeeScript 使用显式的空白来区分代码块. 你不需要使用分号 ; 来关闭表达式, 在一行的结尾换行就可以了(尽管分号依然可以用来把多行的表达式简写到一行里). 不需要再用花括号来 { } 包裹代码快, 在 函数, if 表达式, switch, 和 try/catch 当中使用缩进.

传入参数的时候, 你不需要再使用圆括号来表明函数被执行. 隐式的函数调用的作用范围一直到行尾或者一个块级表达式.

console.log sys.inspect object → console.log(sys.inspect(object));

函数

函数通过一组可选的圆括号包裹的参数, 一个箭头, 一个函数体来定义. 一个空的函数像是这样: ->

coffeeScript

square = (x) -> x * x
cube   = (x) -> square(x) * x

JavaScript

var cube, square;

square = function(x) {
  return x * x;
};

cube = function(x) {
  return square(x) * x;
};

对象和数组

CoffeeScript 中对象和数组的字面量看起来很像在 JavaScript 中的写法. 如果单个属性被写在自己的一行里, 那么逗号是可以省略的. 和 YAML 类似, 对象可以用缩进替代花括号来声明.

coffeeScript

song = ["do", "re", "mi", "fa", "so"]

singers = {Jagger: "Rock", Elvis: "Roll"}

bitlist = [
  1, 0, 1
  0, 0, 1
  1, 1, 0
]

kids =
  brother:
    name: "Max"
    age:  11
  sister:
    name: "Ida"
    age:  9

JavaScript

var bitlist, kids, singers, song;

song = ["do", "re", "mi", "fa", "so"];

singers = {
  Jagger: "Rock",
  Elvis: "Roll"
};

bitlist = [1, 0, 1, 0, 0, 1, 1, 1, 0];

kids = {
  brother: {
    name: "Max",
    age: 11
  },
  sister: {
    name: "Ida",
    age: 9
  }
};

词法作用域和变量安全

CoffeeScript 编译器会考虑所有变量, 保证每个变量都在词法域里适当地被定义 — 你永远不需要自己去写 var.

CoffeeScript

outer = 1
changeNumbers = ->
  inner = -1
  outer = 10
inner = changeNumbers()

JavaScript

var changeNumbers, inner, outer;

outer = 1;

changeNumbers = function() {
  var inner;
  inner = -1;
  return outer = 10;
};

inner = changeNumbers();

注意所有变量的定义都被推到相关的顶层作用域, 也就是第一次出现的位置. outer 在内层的函数里没有被重新定义, 因为它已经存在于作用域当中了. 同时, 内层函数里的 inner 不应该改变外部的同名的变量, 所以在这里有自己的声明.

循环和推导式

你可以使用CoffeeScript将大多数的循环写成基于数组、对象或范围的推导式(comprehensions)。 推导式替代(编译为)for循环,并且可以使用可选的子句和数组索引值。 不同于for循环,数组的推导式是表达式,可以被返回和赋值。

CoffeeScript

# 吃午饭.
eat food for food in ['toast', 'cheese', 'wine']

# 精致的五道菜.
courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']
menu i + 1, dish for dish, i in courses

# 注重健康的一餐.
foods = ['broccoli', 'spinach', 'chocolate']
eat food for food in foods when food isnt 'chocolate'

JavaScript

var courses, dish, food, foods, i, _i, _j, _k, _len, _len1, _len2, _ref;

_ref = ['toast', 'cheese', 'wine'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  food = _ref[_i];
  eat(food);
}

courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'];

for (i = _j = 0, _len1 = courses.length; _j < _len1; i = ++_j) {
  dish = courses[i];
  menu(i + 1, dish);
}

foods = ['broccoli', 'spinach', 'chocolate'];

for (_k = 0, _len2 = foods.length; _k < _len2; _k++) {
  food = foods[_k];
  if (food !== 'chocolate') {
    eat(food);
  }
}

操作符和 aliase

由于操作符 == 常常带来不准确的约束, 不容易达到效果, 而且跟其他语言当中意思不一致, CoffeeScript 会把 == 编译为 ===, 把 != 变异为 !==. 此外, is 编译为 ===, 而 isnt 编译为 !==.

not 可以作为 ! 的 alias 使用.

逻辑操作方面, and 编译为 &&, 而 or 编译为 ||.

在 while, if/else, switch/when 的语句当中, then 可以被用来分隔判断条件跟表达式, 这样就不用强制写换行或者分号了.

就像 YAML, on 和 yes 跟 true 是一样的, 而 off 和 no 是布尔值 false.

unless 可以认为是 if 相反的版本.

this.property 简短的写法可以用 @Property.

可以用 in 判断数据在数组中是否出现, 而 of 可以探测 JavaScript 对象的属性是否存在.

为了简化数学表达式, ** 可以用来表示乘方, // 表示整除, %% 提供数学的模运算(译注: true mathematical modulo?).

完整的列表:

CoffeeScript	JavaScript
is	           ===
isnt	         !==
not	            !
and           	&&
or	             ||
true, yes, on	  true
false, no, off	false
@, this	        this
of	           in
in	         no JS equivalent
a ** b	     Math.pow(a, b)
a // b	     Math.floor(a / b)
a %% b	       (a % b + b) % b

江上有感

江岸郎情,前朝栏杆,不能拍,
河堤妾意,妖娆柳腰,不堪抚,
余辉仍在,故人已远,不曾想,
晚风轻抚,多情离别,不甚伤。

2015-09-08-反思

突然觉得有必要找一个地方写写,想想,说说,无关他人,只是自己,不悲伤,不欢喜,只是静静的谈谈自己。以前说过总有一个时候一个人会回过头来看看身后,身后的脚印也好,石头磕绊也好,必须有一个时辰拿来检讨自己。或许他人不知道,但是自己,自己的良善会知道。
必须要承认自己的过错,比如很容易激动,听不下去别人的言语,尤其是自己不喜欢,不感兴趣,不符合自己的价值观,针对自己的等等。还比如自己现在的随意,满不在乎的样子,其实我也不知道自己以后会在意什么,但是,我觉得这个状态持续下去不太好。
听别人的故事,会流着自己的泪,那么这个泪是否有一部分是为自己而流的呢。很多时候告诉自己不后悔,其实经常会回想自己与她人的点点滴滴。医生中总有那么一个人,会给你不一样的体验,终生难忘。尽管不是时时刻刻,但是几乎每天空下来的时候总会无端想起,不知道这是否是后悔的一种表现呢,可是依然要表现出不在乎的样子。放下就会好过许多,真的是这样的放下么?真的就这样么?

基于 Promise 的 HTTP 请求客户端,axios

基于 Promise 的 HTTP 请求客户端,可同时在浏览器和 node.js 中使用

功能特性

  • 在浏览器中发送 XMLHttpRequests 请求
  • 在 node.js 中发送 http请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求和响应数据
  • 自动转换 JSON 数据
  • 客户端支持保护安全免受 XSRF 攻击

浏览器支持

安装

使用 bower:

$ bower install axios

使用 npm:

$ npm install axios

例子

发送一个 GET 请求

// Make a request for a user with a given ID
axios.get('/user?ID=12345')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (response) {
    console.log(response);
  });

// Optionally the request above could also be done as
axios.get('/user', {
    params: {
      ID: 12345
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (response) {
    console.log(response);
  });

发送一个 POST 请求

axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (response) {
    console.log(response);
  });

发送多个并发请求

function getUserAccount() {
  return axios.get('/user/12345');
}

function getUserPermissions() {
  return axios.get('/user/12345/permissions');
}

axios.all([getUserAccount(), getUserPermissions()])
  .then(axios.spread(function (acct, perms) {
    // Both requests are now complete
  }));

无状态函数式组件

简介

在大部分React代码中,大多数组件被写成无状态的组件,通过简单组合可以构建成其他的组件等;这种通过多个简单然后合并成一个大应用的设计模式被提倡。

形式上表现为一个只带有一个render方法的组件类,通过函数形式或者ES6 arrow function的形式在创建,并且该组件是无state状态的

特点:

  • 组件不会被实例化,整体渲染性能得到提升
    因为组件被精简成一个render方法的函数来实现的,由于是无状态组件,所以无状态组件就不会在有组件实例化的过程,无实例化过程也就不需要分配多余的内存,从而性能得到一定的提升。
  • 组件不能访问this对象
    无状态组件由于没有实例化过程,所以无法访问组件this中的对象,例如:this.ref、this.state等均不能访问。若想访问就不能使用这种形式来创建组件
  • 组件无法访问生命周期的方法
    因为无状态组件是不需要组件生命周期管理和状态管理,所以底层实现这种形式的组件时是不会实现组件的生命周期方法。所以无状态组件是不能参与组件的各个生命周期管理的。
  • 无状态组件只能访问输入的props,同样的props会得到同样的渲染结果,不会有副作用

代码实现

// React.createClass
var Text =  React.createClass({
.....
});

//es5 React.Component
class Text extends React.Component {
  render() {
    return <p>{this.props.children}</p>;
  }
}

//函数式声明组件
const Text = (props) =>
  <p>{props.children}</p>;

补充:

无状态组件内部其实是可以使用ref功能的,虽然不能通过this.refs访问到,但是可以通过将ref内容保存到无状态组件内部的一个本地变量中获取到。
例如下面这段代码可以使用ref来获取组件挂载到dom中后所指向的dom元素:

function TestComp(props){
    let ref;
    return (<div>
        <div ref={(node) => ref = node}>
            ...
        </div>
    </div>)
}

参考

关于react无状态组件(函数式组件)
React创建组件的三种方式及其区别

ssh 权限问题

centos 下必须保证
/var/empty/sshd 权限为744 否则回连接不上ssh。

如果登陆不上可进入管理后台连接进入,重置一下权限。

chmod 744 /var/empty/sshd
//  更改权限后需要重启ssh
service sshd restart

项目结构详解

主要备忘,同时浅析项目结构,和实际项目中的一些应用和写法。

React 开发框架

结构图:

依赖

配置

  • webpack
  • babel
  • eslint
  • flow
  • ….

开发目录

  • assets
  • components
  • frame

redux

actions

创建各个 action 导出 action 名称,action type 和 action handler。

reducers

封装各个action 和 state

store

  • createStore
    初始化store
  • middlewares
    中间件

router

路由

utils

  • cookie 处理

  • ajax 数据请求封装

  • logger 配置

  • ConnectDecorator
    将组件转成高阶组件包裹connect

  • AsyncLoadingDecorator
    按需异步加载装饰器
    react-loadable

  • createReducer
    创建reducer

  • view

  • index.js

Ubuntu安装BTSync

BTSync是多台电脑之间同步文件的利器,很好用。

在Ubuntu上安装BTSync的步骤:

添加btsync官方的Repository

以下命令新建一个 /etc/apt/sources.list.d/btsync.list 文件。

sudo sh -c 'echo "deb http://linux-packages.getsync.com/btsync/deb btsync non-free" > /etc/apt/sources.list.d/btsync.list'

安装BTSync的Public key

使Ubuntu信任此BTSync提供的Repository。

wget -qO - http://linux-packages.getsync.com/btsync/key.asc | sudo apt-key add -

安装

接下来就能用apt-get安装BTSync了,需要先update一下。

sudo apt-get update
sudo apt-get install btsync

创建用于同步的目录

安装默认创建了一个btsync用户,可以创建一个新目录并授权给btsync用户,以后同步的内容就放在这个目录下。

sudo mkdir /home/btsync
sudo chown btsync /home/btsync

使BTSync自动启动

默认启动服务的用户是btsync

sudo systemctl enable btsync

除了enable,systemctl命令还可以带disable、start、stop、status等参数。

通过web设置BTSync

在本地用浏览器访问localhost:8888即可。

如果是VPS或Ubuntu server等没有图形界面的系统,可以编辑BTSync的配置文件。

sudo vi /etc/btsync/config.json

找到下面内容:

"webui" :
{
    "listen" : "127.0.0.1:8888"
    //"listen" : "0.0.0.0:8888", 外网访问
    "login" : "yourusername",
    "password" : "yourpassword"
}

将 “127.0.0.1:8888” 修改为 “0.0.0.0:8888” ,保存退出。重启BTSync。
然后就能用其他机器的浏览器访问 “Ubuntu_IP:8888” 来设置BTSync。

一个可用于生产环境的开发框架的搭建

gitRepo: ➡️

环境

  • mac
  • React 15.5.4
  • react-router v4
  • webpack 3.5.5
  • typescirpt
  • ..

生产需求

一个可以用于线上环境构成要素有:

  • 可靠的编码环境
  • 可靠和发展良好的语言
  • 模块化,包括js 和 css 都要模块化
  • 强类型,方便类型检测和推断
  • 强大的构建工具
  • 路由层面按需加载
  • 统一的api 请求处理

初步结论

  • Mac 或者linux 对编程语言良好支持的操作系统
  • javascript 或者 ES6(ES7) 基本语言
  • 而强类型需要引入 typescript
  • 同时需要通过 webpack 和其第三方插件支持一些 css 模块化和按模块打包按需加载
  • axios 统一封装 api 请求,后期可以更换 fetch 等 异步请求

所以下面我们来示范一个组件的写法

import React, {Component} from 'react'
import PropTypes from 'prop-type'
import ReactDom from 'react-dom'
import EventEmitter from 'events'
import classnames from 'classnames'
import Cssmodule from 'react-css-module'
import {Seq} from 'immutable'
import {immutableRenderDecorator} from 'react-immutable-render'
import {motion, spring} from 'react-motion' //动画特效
import Styles from './app.scss' // css 模块化



@immutableRenderDecorator // Decorator 
@Cssmodules(styles, {allowMutiple: true}) // 模块化
Class TabPane extends Component {
	static PropTypes = {
		tab: Proptypes.oneOfType([
			Propstypes.string,
			Propstypes.node
		]).isRequired,
		order: PropTypes.string.isRequired,
		disable: PropTypes.boolean,
		isActive: PropTypes.boolen
	}

	render() {
		const {className, isActive,children} = this.props;
		const classes = classnames({
						panel: true,
						contentActive: isActive,
					});
	return(
		<div
			role="tabpanel"
			styleName={classes}
 			aria-hidden={!isActive}>
		{children}
		</div>
	)
	}
}

javascript 精粹

javascript 精粹

方法定义函数

Funtction.prototype.method = function (name, func) {
	this.prototype[name] = func;
	return this;
}

语法

  • 空白(space)

注释用// 避免一些错误
例如

/*
	var rm_a = /a*/.match(s)
*/
  • 标识符

字母开头 加上字母,数字,下划线

  • 数字

JavaScript 只有一个数字类型 为64位浮点数
NaN 表示不能产生正常的运算结果, 可以用isNaN(number)检测NaN
Infinity 表示 大于 1.7969313482315704+308的值

  • 字符串

\ 反斜杠 是转义字符
所有字符都是Unicode (16位字符集)

  • 语句

当做假(falsy)

false
null
undefined
空字符串 ‘ ’
数字 0
数字 NaN

for in 语句 枚举一个对象的所有属性

  • 表达式

运算符优先级

运算符 说明
. [] () 提取属性与调用函数
delete new typeof + - 一元运算符
* / % 乘法 除法 求余
+ - 加法/链接 减法
>= <= > < 不等式运算
=== !=== 等式运算符
&& 逻辑与
| | 逻辑或
? : 三元
  • 字面量

创建新对象的表示法

  • 函数

函数字面量定义函数值,可以有一个可选的名字,用于递归调用自己

对象

JavaScript 简单数据类型 数字、字符串、布尔值、null值和undefined
其他所有值都是对象。

  • 对象字面量

一个对象字面就是包围再一堆花括号中的零或多个“名/值"对。

	var empty_object = {};
	var stooge = {
		"first-name": "Jerome",
		"last-name": "Howard"
	}
  • 检索

检索对象里包含的值
[] 后缀中括住一个字符串表达式的方式

	stooge["first-name"]
	flight.departure.IATA
  • 更新

对象里的值可以通过赋值语句来更新
如果不存在会扩充到该对象中

stooge['middle-name'] = 'Lester'
  • 引用

对象通过引用来传递,它们永远不会被复制

	var x = stooge;
	x.nickname = 'Curly';
	var nick = stooge.nickname;
  • 原型

每个对象都链接到一个原型对象,并且它可以从中继承属性。
所有通过字面量对象创建的对象都连接到 Object.prototype,它是JavaScript标配对象

if(typeof Object.beget !== 'function') {
	Object.create = function (o) {
		var F = function () {};
		F.prototype = o;
		return new F();
	}
}
  • 反射

typeof 确定对象的属性

typeof flight.toString // 'function'
typeof flight.constructor //'function'

hasOwnPerty 不检查原型链 如果对象拥有独有的属性 返回true

flight.hasOwnProperty('number') // true
flight.hasOwnProperty('constructor')    //false
  • 枚举

for in 遍历一个对象的所有属性 用hasOwnProperty 或者typeof 来排除函数

var name;
for (name in anoter_stooge) {
	if (typeof anoter_stooge[name] !== 'function') {
		document.writeln( name + ': ' + anoter_stooge[name]);
	}
}
  • 删除

delete 运算符可以用来删除对象的属性。如果对象包含该属性,那么该属性就会被移除。它不影响原型链中的任何属性。

another_stooge.nickname  // 'Moe'

//删除 anoter_stooge 的nickname 属性, 从而暴露出原型的nickname属性
delete anoter_stooge.nickname

another_stooge.nickname   // ‘Curly'
  • 减少全局变量污染

全局变量削弱了JavaScript的灵活性,应该避免使用。
最小化使用全局变量的方法之一是为你的应用只创建一个唯一的全局变量
还有就是应用闭包隐藏信息,从而减少全局污染

var MYAPP = {};

MYAPP.stooge = {
	"first-name": "Joe",
	"last-name": "Howard"
};

MYAPP.flight = {
	airline: "Oceanic",
	number: 815,
	departure: {
		IATA: "SYD",
		time: "2014-09--22 14:45",
		city: "Sydney"
	},
	arrival: {
		IATA: "LAX"
		time: "2004-09-23",
		city: "Los angeles"
	}

};
...

函数

  • 函数对象

JavaScript 中的函数就是对象。
对象的字面量产生的对象连接到Object.prototype
函数对象连接到Function.prototype(该原型对象本身连接到Object.prototype)

函数创建时拥有两个隐藏属性

- 函数上下文
- 实现函数行为的代码

函数对象的prototype 属性的值拥有constructor 属性且值位该函数的对象

  • 函数字面量
//创建一个名为add的变量,并用来吧两个数字相加的函数赋值给它

var add = function (a, b) {
	return a+b;
};

包括四个部分

1. 保留字 function 
2. 函数名  它可以省略 ,省略时 即为 匿名函数(anonymous)
3. 圆括号内的 一组参数
4. 花括号的一组语句  函数的主体

函数也可以被定义再其他函数中,一个内部函数处理可以访问自己的参数和变量,同时也能访问把它嵌套再其中的父函数的参数和变量。通过函数字面量创建的函数对象包含一个链接到外部上下文的链接。这称为闭包(closure).

  • 调用

调用一个函数会暂停当前函数的执行,传递控制权和参数给新函数。
除了声明时定义的参数外,每个函数还会接收两个附加的参数 : this 和 arguments。

一共四种调用模式
(初始化关键参数 this 的不同)

1. 方法调用模式
2. 函数调用模式
3. 构造器调用模式
4.apply调用模式

方法调用模式

当一个函数被保存为对象的一个属性时,我们称它位一个方法。
当一个方法被调用时,this 被绑定到该对象。
如果调用表达式包含一个提取属性的动作(即包含一个. 表达式或者 [subscrript]下标表达式),那么它就是被当做一个方法来调用。

// 创建一个myObject 对象 它有一个value 属性和一个increment 方法
// increment 方法接收一个可选的参数。 如果参数不是数字, 那么默认使用数字1

var myObject = {
	value: 0,
	increment: function (inc) {
		this.value += typeof inc === 'undefined' ? inc : 1;
	}
};

myObject.increment();
document.writlen(myObject.value); // 1

myObject.increment(2);
document.writlen(myObject.value);   // 3

函数调用

var sum = add (3,4);

当一个函数并非一个对象的属性时,那么它就是被当做一个函数来调用
this 绑定到全局对象。这是一个语言设计上的错误。
解决方法:

myObject.double = function () {
	var that = this;
	var helper = function () {
		that.value = add(that.value, that.value);
	}
	helper();// 以函数的形式调用helper
};

// 以方法的形式调用 double
myObject.double();
document.writeln(myObject.value);

构造器调用模式

JavaScript 是一门基于原型继承的语言。
一个函数前面带上new 来调用,那么背地里将会创建一个连接到该函数的prototype成员的新对象 ,this 绑定到那个新对象上。

// 创建一个名为 Quo 的构造器函数。

var Quo = function (String) {
	this.status = String;
};

// Quo 的所有实例提供一个名为get_status 的公共方法

Quo.prototype.get_status = function () {
	return this.satus;
};

// 构造一个Quo 实例。
var myQuo = new Quo("confused");
document.writeln(myQue.get_status()):    // "confused"

Apply 调用模式

因为JavaScript 是一门函数式的面向对象编程语言,所以函数可以拥有方法
apply 方法让我们构建一个参数数组传递给调用函数。它允许我们选择this的值。
apply 接收连个参数,一个是要绑定this的值, 第二个是一个参数数组

// 构造一个包含两个数字的数组,并把他们两个相加

var array = [3, 4];
var sum = add.apply(null, array); // sum 值为7

// 构造包含status 成员的对象

var statusObject = {
	status: 'A-OK'
};

// statusObject  并没有继承自Que.prototype,但我们可以再statusObject 上
// 调用get_status 方法,尽管statusObject 并没有一个名为get_status 方法

var status = Quo.prototype.get_status.apply(statusObject);
// status 的值为 'A-OK'
  • 参数

函数调用时会默认有一个 arguments 参数,arguments 可以访问被调用时传递给它的参数列表。

var sum = function () {
	var i,sum = 0;
	for ( i = 0; i < arguments.length; i += 1) {
		sum += arguments[i];
	}
	return sum;
};

document.writeln(sum(4, 8, 15, 16, 23, 42)); // 108
  • 返回

return 语句 用来提前返回

  • 异常

异常是干扰程序的正常流程的不寻常的事故(但并非出乎意料)

var add = function (a, b) {
	if (typeof a !== 'number' || typeof b !== 'number') {
		throw {
			name: 'TypeError',
			message: 'add needs numbers'
		};
		return a + b;
	}
}

throw 语句中断函数的执行,它应该抛出一个exception对象
该exception 对象将被传递到一个try 语句的catch 从句:

// 构造一个try_it 函数 以不正确的方式调用之前的add 函数
var try_it = function () {
	try {
		add("seven");
	} catch (e){
		document.writeln(e.name + ': ' + e.message);
	}
}
  • 扩充类型的功能

JavaScript 允许给语言的基本类型扩充功能。
扩充 Function.prototype 加入method方法,方便添加方法

Funtction.prototype.method = function (name, func) {
	this.prototype[name] = func;
	return this;
}

比如给Number.prototype 增加一个integer方法

Number.method('integer', function () {
	return Math[this < 0 ? 'ceil' : 'floor' ] (this);
})

document.writeln((-10 / 3).integer());  // -3 

不存在时再添加。

Funtction.prototype.method = function (name, func) {
	if (! this.prototype[name]) {
		this.prototype[name] = func;
	}
	return this;
}
  • 递归

递归函数就是会直接或间接的调用自身的一种函数。

汉诺塔

var hanoi = function (disc, src, aux, dst) {
	if (disc > 0) {
		hanoi(disc - 1, src, dst, aux);
		document.writeln('Move disc ' + disc + ' from ' + src + 'to ' + dst);
		hanoi(disc - 1, aux, src, dst);
	}
}
  • 作用域

作用域控制着变量与参数的可见性以及生命周期

  • 闭包

作用域的好处是内部函数可以访问定义他们的外部函数的的参数和变量(除了this和arguments)
函数可以访问它被创建时所处的上下文环境,所以才叫闭包
保护value不被非法更改

var myObject = (function () {
	var value = 0;
	return {
		increment: function (inc) {
			value += typeof inc === 'number' ? inc : 1;
		},
		getValue: function () {
			return value;
		}
	};
}());

定义一个函数,它设置一个DOM节点为黄色,然后把它渐变为白色

var fade = function (node) {
	var level = 1;
	var step = function () {
		var hex = level.toString(16);
		node.style.backgroundColor = '#FFFF' + hex + hex;
		if (level < 15) {
			level += 1;
			setTimeout(step, 100);
		}
	};
	setTimeout(step, 100);
};

fade(document.body);

避免再循环中创建函数,他可能只会带来无谓的基三,还会引起混淆。
我们可以现在循环外创建一个辅助函数,让这个负主函数再返回绑定了当前i的函数

var add_the_handlers =function (nodes) {
	var helper = function (i) {
		return function (e) {
			alert(i);
		};
	};
	var i;
	for (i = 0; i < nodes.length; i += 1) {
		nodes[i].onclick = helper(i);
	}
};
  • 回调

正常模拟服务器响应

request = prepare_the_request();
response = send_request_synchronously(request);
display(response );

这是最自然的写法,但是如果网络上的同步请求会导致客户端进入假死状态。
所以应用异步函数,防止阻塞

request = prepare_the_request();
response = send_request_synchronously(request, function (response){
	display(request);
});
  • 模块

我们可以使用函数和闭包来构造模块

给String 增加一个deentityify 方法, 理想方式是把它放入闭包:

String.method('deentityify', function () {
	// 字符实体表 银蛇字符实体名字到对应的字符
	var entity = {
	quot: '"',
	lt:  '<',
	gt: '>'
	};

	return function () {
	// 这是真正的deenityify 方法。 调用replace
		return this.replace(/&([^&;]+);/g,
			function(a, b) {
				var r = entity[b];
				return typeof r === 'string' ? r : a;
			}
		);
	};
}());
  • 级联

一些方法返回this而不是undefined 就可以启用级联。
在一个级联中,我们可以单独一条语句一次调用同一个对象的很多方法。
Ajax 类库调用例子:

getElement('myBoxDiv')
	.move(350, 150)
	.width(100)
	.height(100);
  • 柯里化(curry)

函数也是值,从而我们可以用有趣的方式去操作函数值。柯里化允许我们把函数传递给它的参数相结合,产生一个新的函数。

var add1 = add.curry(1);
document.writeln(add1(6));   // 7

创建curry需要注意

arguments 数组并非一个真正的数组,所以并没有concat方法。要避开这个问题,我们必须要再两个argumengts数组上都应用slice方法

Function.method('curry', function () {
	var slice = Array.prototype.slice,
	args = slice.appley(arguments),
	that = this;
	return function () {
		return that.apply(null,args.concat(slice.apply(arguments)));
	}
});
  • 记忆

函数可以将先前的操作的结果记录在某个对象里,从而避免无谓的重复运算。

以Fibonacci 为列

var fibonacci  = function (n) {
	return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2 );
}

for (var i = 0; i <= 10; i += 1) {
	document.writeln('//' + i + ': ' + fibonacci(i));
}

上面fibonacci函数被调用了453次,我们调用了 11次。它调用了吱声442次去计算。

改进加入记忆:

var fibonacci = function () {
	var memo = [0,1];
	var fib = function (n) {
		var result = memo[n];
		if (typeof result !== 'number') {
			result = fib(n - 1) + fib (n - 2);
			memo[n] = result;
		}
		return result;
	};
return fib;
}();

fibonacci函数只被调用了29次,我们调用了 11次。它调用了18次去取得之前的存储结果。

推广记忆功能

var memoizer = function (memo, formula) {
	var recur = function (n) {
		var result = memo[n];
		if (typeof result !== 'number') {
			result = formula (recur, n);
			memo[n] = result;
		}
		return result;
	};
	return recur;
};

那么fibonacci 函数就可以这样写

var fibonacci = memoizer([0,1], function (recur, n) {
	return recur (n -1) + recur (n -2);
});

带记忆功能的阶乘函数

var factorial = memoizer ([1,1], function (recur, n) {
	return n*recur(n - 1);
});

Mysql 备忘

mysql

#mysql

抓取 MySQL Table auto_increment 的最大值

直接由 information_schema 找 MySQL Table auto_increment 的最大值, 有下述兩種情況:

  • 此 Table name 於整個 MySQL DB 中是唯一的:
SELECT TABLE_ROWS FROM information_schema.tables WHERE table_name='YOUR_TABLE_NAME';
  • 此 Table name 於整個 MySQL DB 中有多個, 需要指定 DB Name:
SELECT TABLE_ROWS FROM information_schema.tables WHERE table_name='YOUR_TABLE_NAME' AND table_schema = 'YOUR_DB_NAME';

或下述:
use YOUR_DB_NAME; // 抓取自己現在的 Database name 可用: SELECT DATABASE();

SELECT TABLE_ROWS FROM information_schema.tables WHERE table_name='YOUR_TABLE_NAME' AND table_schema = DATABASE();

开启权限

开启远程访问权限

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'IDENTIFIED BY ‘!123456’ WITH GRANT OPTION;

// 刷新权限
FLUSH PRIVILEGES;

redux

flux的流程是:

  • view触发action中的方法;
  • action发送dispatch;
  • store接收新的数据进行合并,触发View中绑定在store上的方法;
  • 通过修改局部state,改变局部view。

redux是:

  • view直接触发dispatch;
  • 将action发送到reducer中后,根节点上会更新props,改变全局view。

参考

redux

生活,需要一些仪式感

最近读了一篇文章,题目是生活,需要一些仪式感我引用一下特有感觉的话:

我向来觉得生活是需要一些仪式感的,这跟矫情无关,而是关于你对生活的热爱,对幸福的敏感,乃至有时候它是一种结束,也是一种开始。

今天的**人的生活方式似乎少了一些情趣,生活节奏越来越匆忙,生命中越来越缺乏仪式感,而没有仪式感,人生就不庄严,心就不安静。

人人都爱蒂凡尼的早餐,可是却鲜少有人扭头看看自己在生活里,仪式感有多么匮乏。

我仔细的将这些句子在口舌咽喉之间来回可以说是像牛一样反刍,一字一句,我虔诚的像基督徒一样,我认为之前我有罪,没有一丝一毫的仪式感,感到空虚,之前的生活突然觉得没有任何意义,我感到莫大的罪孽,我深深的忏悔,我告诫我自己,要给自己一点点的仪式感,如同刷牙洗脸一样将仪式终身进行下去。

我重拾咖啡,将咖啡放入马克杯,再倒入沸水,一切都是那样的充满敬意,神圣无犯,我知道,这是一种仪式,未来我每天都要进行的仪式。我的心在陶瓷勺搅拌之中随着咖啡粉末融化了,那一刻我从心底里觉得我得到了救赎。像极了肖生克越狱成功后的喜悦。

我不能劝导所有人都要喝咖啡,或者喝茶。我想说的是我同意作者的看法,我遵循仪式,我保持我对仪式的虔诚,坚定我的信仰,我以此来慰借我的罪恶灵魂,一杯咖啡喝完,世间那么的美好。

初爱

阶前初见,也似重逢。
粉罗裙,青丝绾,
眉眼情浓,
羞脸粉红生。
长街长,短亭短,
细语呢哝娇做嗔,
膝枕春风稍歇。
梦呓酒醒空屏,
飞雨沾湿罗衣。

2016-04-20

柯里化

在前端面试中,你可能会遇到这样一个涉及到柯里化的题目。

// 实现一个add方法,使计算结果能够满足如下预期:

add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4)(5) = 15;

这个题目的目的是想让add执行之后返回一个函数能够继续执行,最终运算的结果是所有出现过的参数之和。而这个题目的难点则在于参数的不固定。我们不知道函数会执行几次。因此我们不能使用上面我们封装的createCurry的通用公式来转换一个柯里化函数。只能自己封装,那么怎么办呢?在此之前,补充2个非常重要的知识点。

一个是ES6函数的不定参数。假如我们有一个数组,希望把这个数组中所有的子项展开传递给一个函数作为参数。那么我们应该怎么做?

// 大家可以思考一下,如果将args数组的子项展开作为add的参数传入
function add(a, b, c, d) {
    return a + b + c + d;
}
var args = [1, 3, 100, 1];

在ES5中,我们可以借助之前学过的apply来达到我们的目的。

add.apply(null, args); // 105
而在ES6中,提供了一种新的语法来解决这个问题,那就是不定参。写法如下:
```javascript

add(...args); // 105

这两种写法是等效的。OK,先记在这里。在接下的实现中,我们会用到不定参数的特性。

第二个要补充的知识点是函数的隐式转换。当我们直接将函数参与其他的计算时,函数会默认调用toString方法,直接将函数体转换为字符串参与计算。

function fn() { return 20 }
console.log(fn + 10);     // 输出结果 function fn() { return 20 }10

但是我们可以重写函数的toString方法,让函数参与计算时,输出我们想要的结果。

function fn() { return 20; }
fn.toString = function() { return 30 }

console.log(fn + 10); // 40

除此之外,当我们重写函数的valueOf方法也能够改变函数的隐式转换结果。

function fn() { return 20; }
fn.valueOf = function() { return 60 }

console.log(fn + 10); // 70

当我们同时重写函数的toString方法与valueOf方法时,最终的结果会取valueOf方法的返回结果。

function fn() { return 20; }
fn.valueOf = function() { return 50 }
fn.toString = function() { return 30 }

console.log(fn + 10); // 60

补充了这两个知识点之后,我们可以来尝试完成之前的题目了。add方法的实现仍然会是一个参数的收集过程。当add函数执行到最后时,仍然返回的是一个函数,但是我们可以通过定义toString/valueOf的方式,让这个函数可以直接参与计算,并且转换的结果是我们想要的。而且它本身也仍然可以继续执行接收新的参数。实现方式如下。

function add() {
    // 第一次执行时,定义一个数组专门用来存储所有的参数
    var _args = [].slice.call(arguments);

    // 在内部声明一个函数,利用闭包的特性保存_args并收集所有的参数值
    var adder = function () {
        var _adder = function() {
            // [].push.apply(_args, [].slice.call(arguments));
            _args.push(...arguments);
            return _adder;
        };

        // 利用隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回
        _adder.toString = function () {
            return _args.reduce(function (a, b) {
                return a + b;
            });
        }

        return _adder;
    }
    // return adder.apply(null, _args);
    return adder(..._args);
}

var a = add(1)(2)(3)(4);   // f 10
var b = add(1, 2, 3, 4);   // f 10
var c = add(1, 2)(3, 4);   // f 10
var d = add(1, 2, 3)(4);   // f 10

// 可以利用隐式转换的特性参与计算
console.log(a + 10); // 20
console.log(b + 20); // 30
console.log(c + 30); // 40
console.log(d + 40); // 50

// 也可以继续传入参数,得到的结果再次利用隐式转换参与计算
console.log(a(10) + 100);  // 120
console.log(b(10) + 100);  // 120
console.log(c(10) + 100);  // 120
console.log(d(10) + 100);  // 120
// 其实上栗中的add方法,就是下面这个函数的柯里化函数,只不过我们并没有使用通用式来转化,而是自己封装
function add(...args) {
    return args.reduce((a, b) => a + b);
}

test

first article

this的指向

在向其他执行上下文的传递中,确保this的指向保持不变

如下面的例子中,我们期待的是getA被obj调用时,this指向obj,但是由于匿名函数的存在导致了this指向的丢失,在这个匿名函数中this指向了全局,因此我们需要想一些办法找回正确的this指向。

var obj = {
    a: 20,
    getA: function() {
        setTimeout(function() {
            console.log(this.a)
        }, 1000)
    }
}

obj.getA();

常规的解决办法很简单,就是使用一个变量,将this的引用保存起来。我们常常会用到这方法,但是我们也要借助上面讲到过的知识,来判断this是否在传递中被修改了,如果没有被修改,就没有必要这样使用了。

var obj = {
    a: 20,
    getA: function() {
        var self = this;
        setTimeout(function() {
            console.log(self.a)
        }, 1000)
    }
}

另外就是借助闭包与apply方法,封装一个bind方法。

function bind(fn, obj) {
    return function() {
        return fn.apply(obj, arguments);
    }
}

var obj = {
    a: 20,
    getA: function() {
        setTimeout(bind(function() {
            console.log(this.a)
        }, this), 1000)
    }
}

obj.getA();

当然,也可以使用ES5中已经自带的bind方法。它与我上面封装的bind方法是一样的效果。

var obj = {
    a: 20,
    getA: function() {
        setTimeout(function() {
            console.log(this.a)
        }.bind(this), 1000)
    }
}

面试纪要

  • react 组件和 element 元素的区别?

element 元素
React 元素(React element),它是 React 中最小基本单位,我们可以使用 JSX 语法轻松地创建一个 React 元素。

组件是由元素构成的。元素数据结构是普通对象,而组件数据结构是类或纯函数。
详细➡️ React中元素与组件的区别 - React小黄书 - SegmentFault 思否

  • react 组件间通信有几种方式?

父组件向子组件通信:使用 props
子组件向父组件通信:使用 props 回调
跨级组件间通信:使用 context 对象
非嵌套组件间通信:使用事件订阅
React 中组件间通信的几种方式 - 简书

  • react 组件的生命周期,在哪个生命周期方法适合发起Ajxa

组件挂载完毕时即调用。生命周期内只会调用一次。
应用场景:通常可以将请求后端数据—— ajax/fetch 放在这里。此时界面上 DOM 已经存在。可以做有关 DOM 的操作。例如 findDOMNode.
Note: 在这里调用 setState 会进行一次额外的 rendering,虽然这会导致两次的 render, 但用户不会察觉这过度的时间。可能要多加考虑的地方是这会导致一定的性能问题。

理解 React 组件的生命周期 - Deadpool Front-end

  • store 是通过哪个方法更新的

组件通过dispatch 出发 action ,reducer 改变 store
深入浅出 - Redux · Issue #4 · berwin/Blog · GitHub

  • webpack 中配置按需加载主要通过什么方法实现?

webpack 按需打包加载 · Issue #8 · eyasliu/blog · GitHub

  • flex 布局
  • ES6

深入浅出ES6

python之pyenv版本控制

当需要多个python共存时,pyenv提供了解决知道

#####安装pyenv

git clone git://github.com/yyuu/pyenv.git ~/.pyenv
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
exec $SHELL -l

#####用pyenv安装python

查看可安装的版本

 pyenv install --list

#####安装指定版本(3.4.0为例)

 pyenv install 3.4.0 -v

#####安装之后要对数据库进行更新

 pyenv rehash

#####设置全局python版本

pyenv global 3.4.0

函数式编程

什么是函数式编程

函数式编程可以理解为以函数作为主要载体的编程方式,用函数去拆解、抽象一般的表达式

优点

  • 语义更加清晰
  • 可复用性更高
  • 可维护性更好
  • 作用域局限,副作用少

函数式编程例子

// 数组中每个单词,首字母大写


// 一般写法
const arr = ['apple', 'pen', 'apple-pen'];
for(const i in arr){
  const c = arr[i][0];
  arr[i] = c.toUpperCase() + arr[i].slice(1);
}

console.log(arr);


// 函数式写法一
function upperFirst(word) {
  return word[0].toUpperCase() + word.slice(1);
}

function wordToUpperCase(arr) {
  return arr.map(upperFirst);
}

console.log(wordToUpperCase(['apple', 'pen', 'apple-pen']));


// 函数式写法二
console.log(arr.map(['apple', 'pen', 'apple-pen'], word => word[0].toUpperCase() + word.slice(1)));

解读

当情况变得更加复杂时,表达式的写法会遇到几个问题:

  • 表意不明显,逐渐变得难以维护
  • 复用性差,会产生更多的代码量
  • 会产生很多中间变量

函数式编程很好的解决了上述问题。首先来看 函数式写法一,它利用了函数封装性将功能做拆解(粒度不唯一),并封装为不同的函数,而再利用组合的调用达到目的。这样做使得表意清晰,易于维护、复用以及扩展。其次利用 高阶函数,Array.map 代替 for…of 做数组遍历,减少了中间变量和操作。

而 函数式写法一 和 函数式写法二 之间的主要差别在于,可以考虑函数是否后续有复用的可能,如果没有,则后者更优。

观点

而我认为函数式编程并不是必须的,它也不应该是一个强制的规定或要求。与面向对象或其他**一样,它也是其中一种方式。我们更多情况下,应该是几者的结合,而不是局限于概念 ————— http://taobaofed.org/

参考资料

Ubuntu使用dnsmasq作本地DNS缓存

使用dnsmasq解决dns劫持,dns污染等问题

安装

sudo apt-get install dnsmasq

配置

修改/etc/resolv.conf文件

sudo vim /etc/resolv.conf  

将原有的内容全部注释,然后在第一行写上

nameserver 127.0.0.1

在/etc目录下新建resolv.dnsmasq文件

#local
nameserver 127.0.0.1
#pbulic+
nameserver 119.29.29.29
#v2ex
nameserver 178.79.131.110
#alibaba
nameserver 223.5.5.5
#onedns
nameserver 112.124.47.27
#dnspod dns+
nameserver 182.254.116.116
#114
nameserver 114.114.114.114
#google2
nameserver 8.8.4.4

编辑“/etc/dnsmasq.conf”文件

sudo gedit /etc/dnsmasq.conf

将resolv-file=放开注释

resolv-file=/etc/resolv.dnsmasq

编辑 /etc/dhcp/dhclient.conf

sudo vim /etc/dhcp3/dhclient.conf 

找到下面这一项 #prepend domain-name-servers 127.0.0.1将前面的“#”删除。这么做的目的是为了在使用自动连接时,能在/etc/resolv.conf文件的第一行添加上“nameserver 127.0.0.1”,这样,dns缓存依然有效。

编辑 etc/default/dnsmasq

sudo vim /etc/default/dnsmasq

找到IGNORE_RESOLVCONF=yes,这一条要删除注释,删掉#号

重启服务

sudo service dnsmasq restart

测试结果:

dig google.com

两次返回结果的时间不一样,第二次一般是0ms;多试几个网址,证明成功了。

测试环境

ubuntu 16.04.
Raspberry Pi 2 B+

ES6 知识点整理

ES6

什么是ES6

ECMAScript 标准的历史版本分别是 1、2、3、5。

ES4 太过激进,被废止。

ES5

Object.create() 、 Object.defineProperty() 、
.map() 、 .filter() …

ES6

箭头函数、字符串插值、代理、生成器..
Map 、 Set对象

迭代器和 for - of 循环

for - in 为普通对象遍历自身属性
forEach 不能 break

for - in 正确遍历数组、切能响应 break 、 continue 和 return

Symbol 对象 、 独有不冲突

迭代器对象

生成器

生成器是迭代器。所有的生成器都有内建.next()和 Symbol.iterator方法的实现。你只须编写循环部分的行为

function* range(start, stop) {
  for (var i = start; i < stop; i++)
yield i; 
}

模板字符串

与普通字符串不同的是,模板字符串可以多行书写.模板字符串中所有的空格、新行、缩进,都会原样输出在生成的字符串中

不定参数和默认参数

不定参数

ES6 提供了一种编写可 变参函数的新方式

arguments 对象

ES5

function containsAll(haystack) {
for (var i = 1; i < arguments.length; i++) {
  var needle = arguments[i];
  if (haystack.indexOf(needle) === -1) {
    return false;
  }
}
return true;
}

ES6

function containsAll(haystack, ...needles) {
  for (var needle of needles) {
    if (haystack.indexOf(needle) === -1) {
     return false;
		} 
	}
  return true;
}

默认参数

没有默认值的参数隐式默认为 undefined
传递 undefined 值等效于不传值

解构 Destructuring

数组解构赋值

[ variable1, variable2, ..., variableN ] = array;

被解构的值需要被强制转换为对象。大多数类型都可以被转换为对象, 但 null 和 undefined 却无法进行转换。当使用数组赋值模式时,被解构的值一定要包含 一个迭代器。

默认值

解构的实际应用

  • 函数参数定义

设计一个 对象作为参数,然后将不同的实际参数作为对象属性,以避免让 API 使用者记住 多个参数的使用顺序.

  • 配置对象参数

给需要解构的对象属性赋予默认值

  • 与 ES6 迭代器协议协同使用
var map = new Map();
map.set(window, "the global");
map.set(document, "the document");
for (var [key, value] of map) {
  console.log(key + " is " + value);
}
  • 多重返回值
function returnMultipleValues() {
  return [1, 2];
}
var [foo, bar] = returnMultipleValues();

箭头函数 Arrow Functions

// ES5
var total = values.reduce(function (a, b) {
return a + b;
}, 0);
// ES6
var total = values.reduce((a, b) => a + b, 0);

箭头的{被解析为块的开始,而不是对象的开始

// 为与你玩耍的每一个小狗创建一个新的空对象
var chewToys = puppies.map(puppy => {}); // 这样写会报 Bug! var chewToys = puppies.map(puppy => ({})); //

箭头函数没有它自己的 this 值,箭头函数内的 this 值继承自外围作用域

通过 object.method()语法调用的方法使用非箭头函数定义,这些函数需要从调用者 的作用域中获取一个有意义的 this 值。

// ES6 {
  ...
  addAll: function addAll(pieces) {
    _.each(pieces, piece => this.add(piece));
  },
... }

更简洁的对象字面量

// ES6 的方法语法 {
  ...
  addAll(pieces) {
    _.each(pieces, piece => this.add(piece));
  },
...}

Symbols

第七种基本类型

symbol 是程序创建并且可以用作属性键的值,并且它能避免命名冲突的风险。

Undefined 未定义
Null 空值
Boolean 布尔类型
Number 数字类型
String 字符串类型
Object 对象类型
var mySymbol = Symbol();
obj[mySymbol] = "ok!"; // 保证不会冲突
console.log(obj[mySymbol]); // ok!

获取 symbol 的三种方法

  • 调用 Symbol()
  • 调用 Symbol.for(string)
  • 使用标准定义的 symbol,例如:Symbol.iterator

集合

  • Set
  • Map
  • WeakMap 和 WeakSet
WeakMap 只支持 new、has、get、set 和 delete。 
WeakSet 只支持 new、has、add 和 delete。
WeakSet 的值和 WeakMap 的键必须是对象。

代理 Proxies

对象

对象是在 JS 程序中拥有[[Get]]、[[Set]]等操作的实体

  • 对象都有属性。你可以 get、set 或删除它们或做更多操作。
  • 对象都有原型。这也是 JS 中继承特性的实现方式。
  • 有一些对象是可以被调用的函数或构造函数

ECMAScript 标准委员会定义了一个由 14 种内部方法组成的集合ECMAScript 2015 Language Specification – ECMA-262 6th Edition,你可以调用、删除或 覆写普通方法,但是无法操作内部方法。

代理(Proxy)
它可以接受两个参数:目标对象(target)与句柄对象(handler)

var target = {}, handler = {};
var proxy = new Proxy(target, handler);

类 Class

let 和 const

let 是更完美的 var

  • let 声明的变量拥有块级作用域
  • let 声明仍然保留了提升的特性,但不会盲目提升
  • let声明的全局变量不是全局对象的属性
  • 形如for (let x...)的循环在每次迭代时都为x创建新的绑定
  • et 声明的变量直到控制流到达该变量被定义的代码行时才会被装载,所以在到 达之前使用该变量会触发错误。
  • 用 let 重定义变量会抛出一个语法错误(SyntaxError)

const

const 声明的变量只可以在声明时赋值,不可随意修改,否则会导致 SyntaxError(语法错误)。

ES6 添加了块作用域, for 循环作用域,新的全局 let 作用域,模块作用域,以及求参数的默认值时使用的附加 作用域。

子类 Subclassing

原型继承,即使在 JavaScript 中类继承 的本质也是原型继承)的近类函数

如果不希望创建出来的实例继承自 Object.prototype,你甚至可以在 extends 后使用 null 来进行声明。

Super 属性

子类化内建方法

派生类构造函数

当我们执行基类的构造函 数前,this 对象没有被分配,从而我们无法得到一个确定的 this 值。因此,在子类的 构造函数中,调用 super 构造函数之前访问 this 会触发一个引用错误 (ReferenceError)。

new.target

class foo {
    constructor() {
       return new.target;
    }
}
class bar extends foo {
// 为了清晰起见我们显式地调用 super。 // 事实上不必去获取这些结果。 constructor() {
super(); 
}
}
// 直接调用 foo,所以 new.target 是 foo
new foo(); // foo
// 1) 直接调用 bar,所以 new.target 就是 bar
// 2) bar 通过 super()调用 foo,所以 new.target 仍然是 bar new bar(); // bar

我们新添加的元属性 new.target 与构造函数有关,因为直接通过 new 来 调用,所以它是一个被调函数,在这个函数中调用 super 会传递 new.target 的值

模块 Modules

export

export 列表可以在模块文件最外层作用域的每一处声明,不一定非要把它放在模 块文件的首行。你也可以声明多个 export 列表,甚至通过其它的 export 声明打造一个 混合的 export 列表,只要保证每一个被导出的名称是唯一的即可。

重命名 import 和 export

 // suburbia.js
// 这两个模块都会导出以`flip`命名的东西。
// 要同时导入两者,我们至少要将其中一个的名称改掉。 import {flip as flipOmelet} from "eggs.js"; import {flip as flipHouse} from "real-estate.js";

Default exports

let myObject = {
  field1: value1,
  field2: value2
};
export {myObject as default};
           

简略的表达方法

export default {
  field1: value1,
  field2: value2
};

关键字 export default 后可跟随任何值:一个函数、一个类、一个对象字面量, 只要你能想到的都可以。

模块对象

import * as cows from "cows";

当你 import *时,导入的其实是一个模块命名空间对象,模块将它的所有属性都 导出了。所以如果“cows”模块导出一个名为 moon()的函数,然后用上面这种方法“cows” 将其全部导入后,你就可以这样调用函数了:cows.moo()。

聚合模块

当你通知 JS 引擎运行一个模块时,它一定会按照以下四个步骤执行下
去:
语法解析:阅读模块源代码,检查语法错误。
加载:递归地加载所有被导入的模块。这也正是没被标准化的部分。
连接:每遇到一个新加载的模块,为其创建作用域并将模块内声明的所有绑定填充
到该作用域中,其中包括由其它模块导入的内容。
如果你的代码中有 import {cake} from "paleo"这样的语句,而此时“paleo”模块
并没有导出任何“cake”,你就会触发一个错误。这实在是太糟糕了,你都快要运行模块 中的代码了,都是 cake 惹的祸!
运行时:最终,在每一个新加载的模块体内执行所有语句。此时,导入的过程就已 经结束了,所以当执行到达有一行 import 声明的代码的时候......什么都没发生!

实用特性

  • Object.assign(target, ...sources)。一个新的标准库函数,与 Underscore 中的 _.extend()类似。

热爱工作热爱生活

概要

每个人在开始工作初期,树立远大理想,追求一个卓越的人生。但最终,人追求的是快乐。现阶段的社会,过于急功近利,大多数的人都淹没在了欲望的海洋里,最终忘记了最初的梦想,沦为平庸。当然有的人会认为有很多钱才能快乐,被别人认可也会感到快乐,但是如果一直重复着平庸琐碎的工作,你一定不会快乐。所以我们要追求快乐,在追求快乐的过程中,或许你的荷包会越来越鼓,你的名声越来越大,但请不要忘记,这只是追求快乐的过程中所带来的附加产品。我提供两个建议:

  • 不要害怕失败
  • 制定自己的计划

软件是一门生意

软件是一门生意,程序员是一个生意人。把职业想象成一个产品的生命周期,主要有四个方面用于职业发展。

选择市场

在市场的选择上,有很多要考虑的因素,比如技术的稳定性,技术的发展前景,还有技术人员的供需关系,当你确定之后你要努力的了解你工作的公司所处的行业,只有你熟悉你所在行业,才能更好的完成产品。同时你也要努力发展自身,你不需要成为一名专家,你得成为一名通才,你必须理解程序运行的过程,编译原理,还要预计会出现什么问题,解决这个问题需要什么样的技术?然后是否值得花费时间去接触和学习,对自己未来有什么帮助。一个产品发布的同时,要学会分享,分享给同事,经理等等。。

投资

要做一个机会主义者,抓住身边的机会,努力提高自己,拓展自己的知识面,接触不同的行业,明白每个行业的盈利模式,学习软件开发的步骤。这个过程可能会需要一个老师,这个老师不是传统意义上的老师,他只是这一个行业的标杆,你向他看齐学习这个行业的一切。最后只要不断的练习,练习,练习。

执行

执行是对自己行为的一种定义,简单来说要低调。你必须要有一颗雄心,但不必路人皆。你可以适当从一些字里行间或交谈间了解到经理或者客户需要什么样的功能,然后如果可以就去完成它,说不定将来经理会提出开发这个功能,而你已经做完了。同时要给自己制定计划,每天都要写日志,每周都有总结,每个月都有目标,每年都会规划好发展道路。最后你必须专注现在的工作,因为这让你离未来的目标更近,同时每天都要思考怎么把手头的工作做好。

要明白自己的价值所在,每天都可以问自己我今天创造了多少价值。价值的多少跟时间没有什么太大的关联,每天8小时激情燃烧,就已经最大限度的创造价值了,时间再长也只是浪费自己宝贵的时间而已。在工作中必须保持紧迫感,因为没有人是无可替代的,当你的创造出的产值远远小于公司对你的投资,你就要走人了。当然紧迫不是慌乱,要纵览全局,把握自己的位置,每天都要取得一定的进步。取得进步的有效方法是失败和模仿。好的艺术家会抄袭,而巨匠会偷--毕加索,寻求现有的解决方案来解决自己问题这不可耻,但你必须深刻理解解决方案的原理,并从中学习积累到相关经验。

推销 。。。不仅仅是迎合

首先我们来讲一个古老的心理学问题:如果森林里的一棵大树倒下了,却没有人听到它倒下的声音,那么它倒下的时候到底有没有发出声响?正确答案是:“谁会在意这个?”

树倒下可能会制造出了声响,但并没有人听到它倒下的声音,那么树倒下去制造声响的这一事实是无关紧要的。

工作也一样,如果你非常出色,但没有人知道,那你真的优秀吗?谁会在意?

而且人与人之间的评价都是主观的,公司里的绩效考评也是主观的,别人都不知道你,怎么可能会给你高的评价,所以沟通能力很重要,程序员关门敲代码的时代造就过去式了,这个社会,程序员必须要具备一定的沟通能力,写作能力,因为程序员会与经理,客户,同事等等一些人有交流的必要。要成为一个卓越的人。卓越是什么意思,卓越就是值得被关注。你得在别人心里留下好的印象,才能说你优秀甚至卓越。

保持技术领先

现在这个社会发展很快,技术更新,淘汰也很快,需要时刻保持警惕,说不定第二天就失去了工作,要与时俱进。关注一些技术达人,学习他们所关注的一些技术,每天都进步一点。

同时要学会绘制一张职业蓝图,包括自己所经历过的职业,所学过的技能。罗列出职业发展时间表。

职业发展道路中,树立远大目标,但在实现过程中,需要根据实际情况不断进行更正,从实践中学习,不断改变自己的目标。同时要学着独立,不依赖于他人去解决问题。

关山月

去年此门中,
庭榭旧时,
春光三月老,
人面何处?
一时蝶儿舞,
尽付深情,
挽袖荷花香,
半塘婷婷,
信步闲庭晚,
鸣婵炎炎,
将心与你心,
盈盈笑语,
几多情许卿?
怎堪回首,
别时敬亭山,
《关山月》同。

2016-03-13

redux 原理与实现

redux

redux是flux架构的实现,受Elm启发

flux

An application architecture for React utilizing a unidirectional data flow.

flux是随着react一起推出的数据管理框架,它的核心**是单项数据流。

通过react构建view,而react又是数据驱动的,那么解决数据问题就解决了view的问题,通过flux架构管理数据,使得数据可预测。这样 view也变得可预测。

redux中核心就是一个单一的state。state通过闭包的形式存放在redux store中,保证其是只读的。如果你想要更改state,只能通过发送action进行(dispatch(someAction)),action本质上就是一个普通的对象.redux通过reducer来更新state.

主要功能

  • 获取应用state
  • 发送action
  • 监听state变化
const createStore = (reducer, initialState) => {
  // internal variables
  const store = {};
  store.state = initialState;
  store.listeners = [];
  
  // api-subscribe
  store.subscribe = (listener) => {
    store.listeners.push(listener);
  };
  // api-dispatch
  store.dispatch = (action) => {
    store.state = reducer(store.state, action);
    store.listeners.forEach(listener => listener());
  };
  
  // api-getState
  store.getState = () => store.state;
  
  return store;
};

REDUX核心**

  • reducer 和 reduce

被要求很关键,因为reducer并不是定义在redux中的一个东西。而是用户传进来的一个方法。
纯函数也很关键,reducer应该是一个纯函数,这样state才可预测。

reducer

fucntion reducer(state, action) {
    const nextState = {};
    // xxx
    return nextState;
}

reduce

[].reduce((state, action) => {
    const nextState = {};
    // xxx
    return nextState;
}, initialState)

最主要区别在于reduce的需要一个数组,然后累计变化。 reducer则没有这样的一个数组。 reducer累计的时间上的变化,reduce是累计空间上的变化。

  • middlewares
store.dispatch = function dispatchAndLog(action) {
  console.log('dispatching', action)
  let result = next(action)
  console.log('next state', store.getState())
  return result
}
上述代码会在dispatch前后进行打印信息,这样一个最简单的中间件就实现了。如果再加上compose就可以将多个中间件顺序执行。
比如我们还定义了另外几个相似的中间件,我们需要将多个中间件按照一定顺序执行,如下是redux applyMiddleware源码:
// 用reduce实现compose,很巧妙。
function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

// applyMiddleware 的源码
function applyMiddleware(...middlewares) {
  return createStore => (...args) => {
    const store = createStore(...args)
    let dispatch = () => null;
    let chain = [];

    const middlewareAPI = {
      getState: store.getState,
      dispatch: (...args) => dispatch(...args)
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    // 将middlewares组成一个函数
    // 也就是说就从前到后依次执行middlewares
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

// 使用
let store = createStore(
  todoApp,
  // applyMiddleware() tells createStore() how to handle middleware
  applyMiddleware(logger, dispatchAndLog)
)

java基础知识笔记(2)

接口(interface)

  1. 接口不能用于实例化对象
  2. 接口没有构造函数
  3. 接口的所有方法必须是抽象方法
  4. 接口不能包括成员变量,除 static final 修饰外
  5. 接口不能被类继承,只能被类实现
  6. 接口可以多重继承

接口的方法只能是 public abstract 修饰,变量只能public static final修饰

集合框架

  • 接口: 代表集合的抽象数据类型
  • 实现(类):集合接口的具体实现
  • 算法:实现集合接口的对象里的方法,执行一些相关计算

set 和list的区别

  1. set接口实例存储无序且不重复数据

list存储有序且数据可重复
2. set效率低下,删除插入效率高
3. list和数组一样可以动态增长,查找效率高

面向对象

方法的重写规则

  • 参数列表必须完全与被重写方法的相同;
  • 返回类型必须完全与被重写方法的返回类型相同;
  • 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。
  • 父类的成员方法只能被它的子类重写。
  • 声明为final的方法不能被重写。
  • 声明为static的方法不能被重写,但是能够被再次声明。
  • 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为private和final的方法。
  • 子类和父类不在同一个包中,那么子类只能够重写父类的声明- - 为public和protected的非final方法。
  • 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
  • 构造方法不能被重写。
  • 如果不能继承一个方法,则不能重写这个方法。

重载(Overload)

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造器的重载。
重载规则

  • 被重载的方法必须改变参数列表(参数个数或类型或顺序不一样);
  • 被重载的方法可以改变返回类型;
  • 被重载的方法可以改变访问修饰符;
  • 被重载的方法可以声明新的或更广的检查异常;
  • 方法能够在同一个类中或者在一个子类中被重载。
  • 无法以返回值类型作为重载函数的区分标准。

多态存在的三个必要条件

  • 继承
  • 重写
  • 父类引用指向子类对象

抽象类总结规定

  1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
  2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
  3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
  4. 构造方法,类方法(用static修饰的方法)不能声明为抽象方法。
  5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

封装

在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
要访问该类的代码和数据,必须通过严格的接口控制。
封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。
封装的优点

  1. 良好的封装能够减少耦合。
  2. 类内部的结构可以自由修改。
  3. 可以对成员变量进行更精确的控制。
  4. 隐藏信息,实现细节。

javascript 转换

一、取整
1,直接取整(丢弃小数部分)

var num = parseInt(5/3);  // 1

2,四舍五入取整

var num = Math.round(5/3);  // 2

3,向上取整

var num = Math.ceil(5/3);  // 2

4,向下取整

var num = Math.floor(5/3);  // 1

参考连接

保留小数点后N位

Oracle 与 MySql 区别(笔记)

一、并发性

并发性是oltp数据库最重要的特性,但并发涉及到资源的获取、共享与锁定。

mysql:
mysql以表级锁为主,对资源锁定的粒度很大,如果一个session对一个表加锁时间过长,会让其他session无法更新此表中的数据。
虽然InnoDB引擎的表可以用行级锁,但这个行级锁的机制依赖于表的索引,如果表没有索引,或者sql语句没有使用索引,那么仍然使用表级锁。

oracle:
oracle使用行级锁,对资源锁定的粒度要小很多,只是锁定sql需要的资源,并且加锁是在数据库中的数据行上,不依赖与索引。所以oracle对并发性的支持要好很多。

二、一致性

oracle:
oracle支持serializable的隔离级别,可以实现最高级别的读一致性。每个session提交后其他session才能看到提交的更改。oracle通过在undo表空间中构造多版本数据块来实现读一致性,
每个session查询时,如果对应的数据块发生变化,oracle会在undo表空间中为这个session构造它查询时的旧的数据块。

mysql:
mysql没有类似oracle的构造多版本数据块的机制,只支持read commited的隔离级别。一个session读取数据时,其他session不能更改数据,但可以在表最后插入数据。
session更新数据时,要加上排它锁,其他session无法访问数据。

三、事务

oracle很早就完全支持事务。

mysql在innodb存储引擎的行级锁的情况下才支持事务。

四、数据持久性

oracle
保证提交的数据均可恢复,因为oracle把提交的sql操作线写入了在线联机日志文件中,保持到了磁盘上,
如果出现数据库或主机异常重启,重启后oracle可以考联机在线日志恢复客户提交的数据。
mysql:
默认提交sql语句,但如果更新过程中出现db或主机重启的问题,也许会丢失数据。

五、提交方式

oracle默认不自动提交,需要用户手动提交。
mysql默认是自动提交。

六、逻辑备份

oracle逻辑备份时不锁定数据,且备份的数据是一致的。

mysql逻辑备份时要锁定数据,才能保证备份的数据是一致的,影响业务正常的dml使用。

七、热备份

oracle有成熟的热备工具rman,热备时,不影响用户使用数据库。即使备份的数据库不一致,也可以在恢复时通过归档日志和联机重做日志进行一致的回复。
mysql:
myisam的引擎,用mysql自带的mysqlhostcopy热备时,需要给表加读锁,影响dml操作。
innodb的引擎,它会备份innodb的表和索引,但是不会备份.frm文件。用ibbackup备份时,会有一个日志文件记录备份期间的数据变化,因此可以不用锁表,不影响其他用户使用数据库。但此工具是收费的。
innobackup是结合ibbackup使用的一个脚本,他会协助对.frm文件的备份。

八、sql语句的扩展和灵活性

mysql对sql语句有很多非常实用而方便的扩展,比如limit功能,insert可以一次插入多行数据,select某些管理数据可以不加from。
oracle在这方面感觉更加稳重传统一些。

九、复制

oracle:既有推或拉式的传统数据复制,也有dataguard的双机或多机容灾机制,主库出现问题是,可以自动切换备库到主库,但配置管理较复杂。
mysql:复制服务器配置简单,但主库出问题时,丛库有可能丢失一定的数据。且需要手工切换丛库到主库。

十、性能诊断

oracle有各种成熟的性能诊断调优工具,能实现很多自动分析、诊断功能。比如awr、addm、sqltrace、tkproof等
mysql的诊断调优方法较少,主要有慢查询日志。

十一、权限与安全

mysql的用户与主机有关,感觉没有什么意义,另外更容易被仿冒主机及ip有可乘之机。
oracle的权限与安全概念比较传统,中规中矩。

十二、分区表和分区索引

oracle的分区表和分区索引功能很成熟,可以提高用户访问db的体验。
mysql的分区表还不太成熟稳定。

十三、管理工具

oracle有多种成熟的命令行、图形界面、web管理工具,还有很多第三方的管理工具,管理极其方便高效。
mysql管理工具较少,在linux下的管理工具的安装有时要安装额外的包(phpmyadmin, etc),有一定复杂性。

闭包的应用

顺序输出1~5

for (var i=1; i<=5; i++) {
(function(b){
return setTimeout( function timer() {
console.log(b);
}, b*1000 )
})(i)
}

另外集中方式

1.利用setTimeout第三个参数
for (var i=1; i<=5; i++) {
setTimeout( function timer(i) {
console.log(i);
}, i*1000,i );
}
2.利用bind方法
for (var i=1; i<=5; i++) {
setTimeout( function timer(i) {
console.log(i);
}.bind(null,i), i*1000 );
}
3.利用let
for (let i=1; i<=5; i++) {
setTimeout( function timer() {
console.log(i);
}, i*1000 );
}

姜文的一步之遥

一直以来对姜文的电影有种从心底里的欢喜,这个不同于其他国人导演的拍片风格,很是吸引人。从
让子弹飞到一步之遥,都是民国风,个人对民国也有着文青的特殊向往,那个军阀混战的年代,人民
开始追求时尚,追求自由,追求知识,科学等等,一切皆有可能的年代。

姜文谱写了一步之遥,借此讽今,开篇从泡沫出场,预示着本片的电影基调,深刻的批判了当下**
电影的泡沫,终将破灭。To be or not to be. 这便是这部电影的伟大之处,偏要在上映两周年的
今天才能读懂的深意。

主角马走日,性格鲜明。电影中买通不成,便冲动行凶。如果马走日,真的想杀王天王,那他可以事
先谋划,这并不难。但,他却选择在众目睽睽下,挥拳上台“殴打”对方。这足以体现马走日的孩子气,
幼稚的可笑,无论老少都是孩子,用孩子的眼光看待人事。

为解一时之气,宁愿坐牢宁愿被枪毙。

理由很简单,仅为了死去的完颜英的颜面。

傻不傻?

李安说过,周星驰拍的,都是小孩子的东西。

那么《一步之遥》,我给它的定义,就是一部“成人童话”。

它的主题有两个:

讽刺自命成熟者、讽刺自命成熟的社会。

是的,以一个小孩子的视角。

《一步之遥》表面上是部民国题材电影。

但实际上,它一直都在假借历史,讽刺假大空的、诛心吃人的社会。

青卢和白狐,为了争夺花国总统,费尽心思编排出百老汇级别的精彩表演。

我有一个文青朋友,当年她和我说,只看这段歌舞,就已经值回电影票价了。

《一步之遥》的结局,极不符合普通国产片中惯用的套路。

从头到尾,死掉的只有马走日、完颜英,以及半死不活的武六。

其余的人,看客依旧是看客,军阀依旧是军阀,伪艺术家依旧是伪艺术家。

他们依旧挥舞着武器,只不过有的武器是枪,有的武器是目光,有的武器是镜头。

以上灵感来自毒舌电影

## Re: Zero 学习一个组件

#componet

class Clock extends React.Component{
  constructor(props){
    super(props);
    this.state = {date: new Date()}
  }
  
  componentDidMount(){
    this.Timer = setInterval(() => this._tick(), 1000);
  }
  
  componentWillUnMount(){
    clearInterval(this.Timer);
  }
  
  _tick(){
    this.setState({
      date: new Date()
    })
  }
  
  render() {
    return(<div> this is {this.state.date.toLocaleTimeString()}</div>)
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);

知识点

  • ES6 的 class 是小写 小写 小写!!!
  • React.Componet 和 React.createClass
  • 生命周期(生命钩子)
  • 无状态组件和高阶组件
  • render 执行
  • 。。。

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.