Coder Social home page Coder Social logo

blog's People

Watchers

 avatar

blog's Issues

Yarn 工作流

在你的项目中使用包管理器,也就带来了一个关于依赖的新工作流。Yarn 尽可能不增加现有工作的负担,同时使工作流的每一步都简洁易懂。

有些关于基本工作流的事情你应该了解:

  1. 创建新项目
  2. 添加/升级/移除依赖
  3. 安装/重装依赖
  4. 使用版本管理工具(比如 git)

创建新项目

无论是现有的代码目录或仓库,还是将要开始的全新项目,都可以正常使用 Yarn。打开终端或控制台,移至你想添加 Yarn 的目录(应当是项目的根目录),然后运行如下命令:

yarn init

然后会打开一个包含如下配置项的交互表单,用于创建新的 yarn 项目:

name (your-project):
version (1.0.0):
description:
entry point (index.js):
git repository:
author:
license (MIT):

你可以输入内容,也可以敲回车键以保持默认值或空白。

package.json

现在项目中应该产生了一个跟下面内容差不多的package.json文件:

{
  "name": "my-new-project",
  "version": "1.0.0",
  "description": "My New Project description.",
  "main": "index.js",
  "repository": {
    "url": "https://example.com/your-username/my-new-project",
    "type": "git"
  },
  "author": "Your Name <[email protected]>",
  "license": "MIT"
}

当你运行命令yarn init时,所有的工作就是创建这个文件,后台不会进行任何操作。你可以随意修改这份文件。

package.json文件主要用来存放项目的相关信息,包括项目名称、维护者、源码地址等,当然最重要的是安装项目所需的依赖列表。


管理依赖

这里是一些添加、升级、移除依赖时所需要用到的命令。每个命令都会自动更新package.jsonyarn.lock文件。yarn.lock

添加依赖

在引入其他包之前,需要把它作为依赖加入到项目中。运行命令:

yarn add [package]

此命令会自动在package.json中把[package]添加到项目依赖中,同时更新yarn.lock以记录变化。

package.json的变化

通过不同的参数可以添加不同类型的依赖:依赖类型

  • yarn add --dev对应devDependencies类型
  • yarn add --peer对应peerDependencies类型
  • yarn add --optional对应optionalDependencies类型

通过设置依赖版本标签可以使用依赖的特定版本。

举例:

yarn add [email protected]
yarn add package-2@^1.0.0
yarn add package-3@beta
{
  "dependencies": {
    "package-1": "1.2.3",
    "package-2": "^1.0.0",
    "package-3": "beta"
  }
}

升级依赖

yarn upgrade [package]
yarn upgrade [package]@[version]
yarn upgrade [package]@[dist-tag]

package.jsonyarn.lock会随之更新。

升级依赖

移除依赖

yarn remove [package]

同样,package.jsonyarn.lock会随之更新。


安装依赖

从版本控制仓库中取到的包,需要安装其中的依赖。

在项目中添加依赖,这些依赖会在添加时自动安装。

安装

yarn install可用来安装项目里所需的全部依赖。依赖项来自项目的package.json文件,保存在yarn.lock文件中。

在开发的时候,安装依赖主要是在下面2步之后做的:

  1. 刚取到项目代码
  2. 项目的其它开发人员添加了新依赖,你需要保持同步。

安装选项

安装依赖的配置选项有很多,包括:

  • 安装全部依赖:yarnyarn install
  • 装且仅装包的一个版本:yarn install --flat
  • 强制重新下载所有包:yarn install --force
  • 只安装生产版的依赖:yarn install --production

配置选项的完整列表


使用版本控制

为了保证开发成功或包可以被正确使用,要保证所有必需的文件都传至源文件仓库。

必备的文件

下面几个个文件必须传至源文件仓库中,以保证其它人能够管理这个包:

  • package.json:有包当前所用的所有依赖
  • yarn.lock:保存每个依赖的确切版本信息
  • 提供功能的实际源码

示例项目 Yarn Example Package 展示了一个 Yarn 项目的最小组织结构。


持续集成

Yarn可以轻松应用于多种持续集成系统,如AppVeyor, CircleCI, Travis CI

原文地址

Chrome控制台API (console)

除了 log(),Chrome 的 console 还提供很多功能丰富的函数,可以提升工作效率。本文主要参考官方文档

console.assert(expression, object)

如果表达式expression的计算结果是false,则控制台输出一条 error 。内容为object,可以是字符串或其他对象。

例:

assert方法

console.clear()

清空控制台的显示内容。与 Clear console (clear console)按钮,或快捷键 Ctrl + LCommand + K 的功能类似。但是如果打开了 Preserve logconsole.clear() 则不起作用。

更多信息:清空控制台

console.count(label)

输出 label 出现的次数。每调用一次加1(对应同一个label)

label 中可含变量和字符串。对于变量,一个值对应一个 label

★ 没有返回值

console.count

更多信息:记录语句执行次数

console.debug(object [, object, …])

与 console.log() 相同。在控制台的输出结果用蓝色显示。

console.dir(object)

用 JavaScript 风格输出给定 object 的所有属性和方法及其原型。如果给定的对象是 HTML 元素,那么会输出它的 DOM 属性和方法。如下图所示:

console.dir

for...in... 循环简明省事多了

console.dirxml(object)

如果 object 是 XML (或 HTML )元素,那么用 XML 风格输出其后代元素。如果不是则用 JavaScript 风格输出。(相当于 console.log(object)

console.dirxml

console.error(object [, object, …])

输出一条指定的错误信息。语法与 console.log() 相同。

console.error

console.group(object[, object, …])

console.groupEnd() 配套使用。给几条 log 分成一组显示于控制台,并添加可选组名。样式如下图所示:

console.group

★ 分组可以嵌套

console.groupCollapsed(object[, object, …])

console.group() 功能相同,也要与 console.groupEnd() 配套使用。不同之处是输出的分组默认折叠。

console.groupEnd()

结束分组

console.info(object[, object, ...])

console.log() 功能和语法相同,不过在控制台显示一个表示信息的小图标。如图所示 :

console.info

console.log(object[, object, ...])

在控制台输出一条信息。当输入多个对象时,会分别计算,然后拼接成一个用空格分隔的字符串。

★ 支持格式控制字符 %扩展阅读

console.profile([label])

开启一段 JavaScript 的 CPU 性能分析,输入一个可选的标签 label 。调用 console.profileEnd() 来结束。每段分析都会加入 Profiles 面板中。

console.profileEnd()

结束 CPU 性能分析,把结果输出到 Profiles 面板。

console.time(label)

给对应的 label 开启一个计时器。当相同 labelconsole.timeEnd() 被调用时结束计时,并且把时间差输出到控制台。时间精度可达亚毫秒级别。两个函数的参数 label 必须一致,否则计时器不会停止。

console.time

console.timeEnd(label)

停止指定的计时器,并把时间差输出到控制台。

console.timeStamp([label])

在录制时间线( Timeline )的过程中添加一个事件。

更多信息:制作时间线

console.trace(object)

在函数调用处输出一条栈轨迹( stack trace )信息。

console.trace

console.warn(object [, object, ...])

console.log 相同,但是输出的信息带警告风格。

console.warn

console.table(对象)

已表格的形式展示对象的属性和属性值,并把构造函数附在后面(仅Chrome)

对象支持除函数以外的其他对象类型

console对象不仅在浏览器环境中存在,而且在Node环境中也可以用。但是要注意可能存在的细节上的不同。

Linux服务器初始配置

本文的主要内容是针对新创建的Linux远程主机所进行的基本配置

Linux远程主机环境为Ubuntu 16.04,本地环境为 macOS

登录配置

新主机的默认登录用户是root,所以用root身份登录。

修改root用户的密码

# passwd

新建普通用户,用于登录

# adduser usr01

给新建的用户添加密码

# passwd usr01

给用户 usr01 配置SSH密钥登录,比密码登录更安全方便。

修改 /etc/ssh/sshd_config ,不同的发行版本和云服务商所提供的默认配置有所不同,比较关键的内容如下:

PermitRootLogin no        #设置no为禁用root用户登录
StrictModes yes           #设置yes为启用严格模式
PubkeyAuthentication yes  #设置yes为启用SSH公钥登录
PermitEmptyPasswords no   #设置no为禁止使用空密码登录
PasswordAuthentication no #设置no为禁止使用密码登录(需要在确保SSH密钥可以登录后再修改)默认为yes
AllowUsers usr01          #设置允许登录的用户,即新建的登录专用的用户

修改完毕后重启sshd服务 service restart sshd

然后就使用用户 usr01 登录主机。需要root权限时使用su root 切换到root,或单独开启sudo权限

SSH密钥登录

原理

SSH是一种协议标准,目的是实现安全远程登录以及其他安全网络服务。应用最为广泛的实现工具是开源的OpenSSH。

SSH安全传输所使用的加密方式是非对称加密,所以SSH的密钥体系有公钥私钥之分。在client端或server端生成密钥对,然后把私钥保存在client端,把公钥保存在server端(authorized_keys)。

对于非对称加密体系,存在中间人攻击的风险。SSH传输没有HTTPS所使用的证书体系,所以需要在client维护一个server公钥指纹的列表(know_hosts),在client首次登陆server时系统会进行提示是否要添加此server的公钥指纹。

Client生成密钥对

  1. ssh-keygen 生成密钥对:私钥 id_rsa ,公钥 id_rsa.pub。一般位于 ~/.ssh/ 目录下,同时 know_hosts 和 authorized_keys 也位于此目录中。

  2. 需要把公钥 id_rsa.pub 手动发送到远程主机上:

直接使用命令 "ssh-copy-id":ssh-copy-id [-i [identity_file]] [user@]machine 可以代替步骤2和3

scp [-P 端口号] 本地文件地址 远程主机用户@远程主机地址:/tmp
  1. 使用普通用户 usr01 登录远程主机,把公钥追加到用户的 authorized_keys列表中。

    mkdir .ssh
    cat /tmp/id_rsa.pub >> ./.ssh/authorized_keys
    
  2. 检查文件权限

    chmod 600 authorized_keys
    chmod 700 ~/.ssh
    

Server生成密钥对

  1. 使用普通用户 usr01 登录远程主机,执行 ssh-keygen 生成密钥对。
  2. 把公钥添加到 authorized_keys,注意文件权限。把私钥传回本地
  3. 在SSH客户端中使用私钥进行登录

此种方法适合client为Windows系统,使用SSH客户端软件,如PuTTY等。对于Linux和Mac,更推荐在client端生成密钥对。

在Client配置快速登录

当server端的SSH公钥登录配置完毕,client端添加server的公钥指纹之后,client就可以直接登录远程server了。

ssh usr01@远程服务器ip地址

但是每次输入用户名和地址还是颇为不便。这时我们可以利用alias,来进一步简化命令。对于Linux或Mac,依据终端所用的shell,可以给 .bashrc.zshrc 添加alias。以zsh为例,在 .zshrc 的末尾添加:

alias ssh-rs="ssh usr01@远程服务器ip地址"

保存后,在终端中使用 source ~/.zshrc 应用更改。然后就可以使用 ssh-rs 直接进行SSH登录。

使用 nvm 管理多版本 node

nvm(Node Version Manager)是运行在 mac 和 linux 中的多版本 node 管理工具。在 windows 中可以使用 nvm-windows

安装 nvm

安装脚本

使用 curl 下载:

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh | bash

或 wget:

wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh | bash

目前的最新版本是0.33.6,可以前往官方主页查看最新地址。

脚本的默认安装源是 nodejs.org,默认的安装地址是~/.nvm,可以通过 NVM_SOURCENVM_DIRPROFILE,和 NODE_VERSION 手动设置 nvm 的安装源、安装目录、bash 配置文件和 node 版本。例如全局安装 nvm :curl ... | NVM_DIR=/usr/local/nvm bash

安装完成后验证是否安装成功,可以直接运行 nvm ,如果返回

Node Version Manager

Note: <version> refers to any version-like string nvm understands. This includes:
  - full or partial version numbers, starting with an optional "v" (0.10, v0.1.2, v1)
  - default (built-in) aliases: node, stable, unstable, iojs, system
  - custom aliases you define with `nvm alias foo`

 Any options that produce colorized output should respect the `--no-colors` option.

等等一大堆帮助信息,说明安装成功。

或者使用 command -v nvm ,如果返回nvm,则说明安装成功。

通过 Git 安装

要求 git 版本为1.7+

  1. 把本项目 clone 到当前用户的主目录中

    cd ~/
    git clone https://github.com/creationix/nvm.git .nvm
    
  2. cd ~/.nvm 然后 checkout 至最新版本: git checkout v0.33.6

  3. 运行 shell 脚本激活 nvm :. nvm.sh

  4. 把以下内容添加到 ~/.bashrc~/.profile,或 ~/.zshrc 文件中(可能要在多个文件中添加)

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

手动更新

使用 git(1.7+):

  1. 切换到目录 $NVM_DIR
  2. 获取最新变更 git fetch origin
  3. checkout 到最新版
  4. 激活 nvm . "$NVM_DIR/nvm.sh"

使用 nvm

下载并安装最新版的 node:

nvm install node

然后启用最新版 node:

nvm use node

install 成功后,nvm 会自动切换到最新安装的 node 版本,可以直接使用 node -v 查看当前 node 版本

基本命令

  1. 安装:nvm install 版本号/node(最新unstable版)/--lts(最新LTS版)/--lts=指定LTS版
  2. 卸载:nvm uninstall ...
  3. 运行 node 命令:nvm run ... options/文件
  4. 在当前终端的子进程中运行特定版本的 node 命令:nvm exec ... node options/文件
  5. 查看特定版本 node 的安装目录:nvm which ...
  6. 查看本地已安装的版本列表:nvm ls
  7. 查看远程源上的版本列表:nvm ls-remote ,只看LTS版 nvm ls-remote --lts
  8. 增加/修改别名:nvm alias 名称 版本号 ,指定默认 node 版本 nvm alias default node
  9. 删除别名:nvm unalias 名称
  10. 安装/更新到当前 node 版本所支持的最新版 npm:nvm install-latest-npm

在安装时迁移全局 npm 包

把旧版本中已经安装的全局 npm 包迁移至新版本中:

nvm install node --reinstall-packages-from=node

可以分别指定旧版和新版

nvm install 新版 --reinstall-packages-from=旧版

包管理器 Yarn 简介

概述

Yarn 是一个代码管理器。npm 的替代品。Yarn 通过**包(package)**的形式共享代码(有时也叫 module)。一个包内包括代码本身和描述包的package.json文件。


安装

macOS

HomeBrew

如果 Node.js 没有安装的话,通过这种方式也会一并安装。

brew update
brew install yarn

PATH设置

安装完毕后还需要设置PATH环境变量。这样就可以在终端里全局使用 Yarn。把 export PATH="$PATH:$HOME/.yarn/bin" 添加到终端配置文件中。依据终端的不同,此文件可能是.profile.bashrc.zshrc等等。

验证一下

yarn --version

Windows

在 Windows 上的安装方式有2种:

下载安装包

使用.msi格式的安装包来完成安装工作,需要事先成功安装 Node.js

下载地址

通过 Chocolatey 安装

Chocolatey是一个 Windows 平台下的包管理器。
安装 Chocolatey 成功后,可以通过在控制台运行如下代码而进行 Yarn 的安装:

choco install yarn

此方法也要求事先成功安装Node.js

注意

一定要把你的项目文件夹和 Yarn 的缓存目录(%LocalAppData%\Yarn)添加到杀毒软件的白名单中,否则包文件的安装过程会因对每个文件进行的扫描而显著变慢。

验证一下

yarn --version

使用

此处罗列了一些常见命令。更多细节见 Yarn Cli Introduction

开始新项目

yarn init

添加依赖

yarn add [package]
yarn add [package]@[version]
yarn add [package]@[tag]

升级依赖

yarn upgrade [package]
yarn upgrade [package]@[version]
yarn upgrade [package]@[tag]

移除依赖

yarn remove [package]

安装项目的所有依赖

yarn

yarn install

原文地址: https://yarnpkg.com/en/docs/getting-started

Javascript的正则表达式

目录

JavaScript 正则表达式的构成方式

  • 字面量/pattern/flags
    • pattern是表达式文本
    • flags是特殊参数: g ——全局匹配; i ——忽略大小写; m ——让开头(^)和结尾($)字符工作在多行模式(由 \n 或 \r 分割的)
    • 多行模式:每一行的开头结尾也可匹配。关闭多行模式则只匹配整个字符串的开头和结尾
    • 静态常量:构造完成后保持不变
  • 构造函数:new RegExp("pattern","flags")
  • pattern是字符串,注意对 \ 的转义(" \\ ")
  • 运行时编译→表达式可变

表达式文本由普通字符特殊字符以及对应的重复规则组合而成。

例子:/abc/匹配字符串中的'abc'子串

特殊字符

★ 特殊字符都是单个字符!

  • 字符类别
    • .英文句点,小数点——匹配任意单个字符(换行符除外)
    • \d 一个数字[0-9]\D 一个非数字[^0-9]
    • \w 一个字母或数字或下划线[a-zA-Z0-9_]\W 一个非字母非数字非下划线的字符[^a-zA-Z0-9_]
    • \s 一个空白符;\S 一个非空白符
    • \xhh 一个编码为两位十六进制数(hh)的字符(ASCII码)
    • \uhhhh 一个Unicode字符,四位十六进制数
    • 其他:RexExp-MDN
  • 字符集合
    • [abcde] 匹配集合中的任意一个字符。abcde 等价于 a-e
    • [^abcde] 匹配任意一个不在集合中的字符。abcde 等价于 a-e
  • 边界
    • ^ 开头(字符串或每行)
    • $ 结尾(字符串或每行)
    • \b 单词边界
    • \B 非单词边界(内部)

分组

  • 捕获括号 (pattern) :匹配表达式并保存括号内的字符串。
  • replace()函数的第二个参数中使用$1,$2,...$9获取
  • 反向引用 \n (n是正整数):指向正则表达式中左起第 n 个括号所匹配的字符串
  • 非捕获括号 (?:pattern) :匹配但不保存

//不大理解。放上另一个说法:分组用于指定子表达式,单独确定重复次数或其他操作。参考

数量词(表达式或分组的重复次数)

位于表达式后面

  • *:0或多次
  • + :1或多次
  • ? :0或1次
  • {n,} :至少 n 次
  • {n,m}:至少 n 次,至多 m 次

默认匹配模式是贪婪模式,即一个匹配结果包含尽可能多的字符。在上述数量词后加上一个 ? 就设置成非贪婪模式,即一个匹配结果包含尽可能少的字符。

★ 另有一条更高优先级的匹配规则:最先开始的匹配拥有最高优先权

  • {n} :n次(多于 n 时也只匹配n次,无所谓贪婪懒惰)
  • x(?=y) :只有当 x 后面紧跟着 y 时,才匹配 x 。
  • x(?!y) :只有当 x 后面不紧跟着 y 时,才匹配 x 。
  • x|y :匹配 x 或 y 。

CSS简写

盒模型相关

处理盒子边界相关的属性,如 paddingmarginborder-style

  • 1个值:(上下左右)p1
  • 2个值:(上下) (左右)p2
  • 3个值:(上) (水平) (下)p3
  • 4个值:(上) (右) (下) (左)p4

处理盒子四角相关的属性,如 border-radius

  • 1个值:(四角相同)p5
  • 2个值:(左上、右下) (右上、左下)p6
  • 3个值:(左上) (右上、左下) (右下)p7
  • 4个值:(左上) (右上) (右下) (左下) p8

Font属性

font:style variant weight size/line-height family

  • style variant weight、line-height 为可选,size 和 family 必须写。省略可选项表示取默认值

style: normal || italic || oblique

variant: normal || small-caps

weight: normal || bold || bolder || light || lighter ||(100-900, normal===400)

line-height: normal || 数字

size: inherit || 数字

family: inherit || name "more name"

Border属性

border:width style color

Background属性

background: color image repeat position/size attachment clip

  • 顺序可以任意改变,position/size 固定不变
  • 多组background使用逗号分隔,最后一组的color有效

image: none || url(图片相对地址)

size: auto auto || cover || contain

attachment: scroll || fixed || local

clip: border-box || padding-box || content-box

Atom 插件使用记录

记录一个方便“灾后重建”的列表。Atom自带的package管理总是下载失败,只好用笨办法:从github上clone再安装(但是非常有效)。

  • linter-stylelint CSS, SCSS, Less, PostCSS, 和 SugarSS 的语法检查
  • linter-eslint JavaScript语法检查
  • react JSX语言支持、排版、代码片段、自动补全、格式化
  • linter 语法检查器的基础支持
  • build-sass 编译sass/scss
  • atom-beautify 美化HTML, CSS, JavaScript, PHP, Python, Ruby, Java, C, C++, C#, Objective-C, CoffeeScript, TypeScript, Coldfusion, SQL, and more in Atom
  • regex-railroad-diagram 正则表达式的图形化显示
  • color picker 选择颜色,包括 HEX, HEXa, RGB, RGBa, HSL, HSLa, HSV, HSVa, VEC3, VEC4
  • emmet HTML编码增强
  • file-icons 给不同类型的文件添加对应的图标
  • imdone-atom 一个TODOs、FIXMEs、HACKs的任务列表
  • jumpy 动态创建当前标签页内的跳转热键
  • minimap 全部代码的缩略图预览
  • pigments 在代码中显示颜色数值对应的颜色
  • atom-ternjs javascript的自动补全
  • run-in-brwoser 在浏览器中打开html文件
  • Elastic Tabstops Elastic Tabstops for Atom

参考

  1. Awesome Atom
  2. Awesome Mac

使用 pyenv 下载 python 安装包时没有响应

问题描述

运行 pyenv install x.x.x 之后,流程卡在下载这步不动了。

原因

主要是在于 pyenv 默认连接的安装源的下载速度特别慢(跟 Amazon S3 有关),然后 pyenv 的下载界面也没有任何关于速度或进度的提示。好在 pyenv 支持本地安装。

环境

macOS Sierra 10.12.6 + Xcode 8.3.3

解决方法

1. 直接从国内源下载 python 版本的安装包Python-3.6.2.tar.xz到本地(以 python 3.6.2 为例)

  • 我使用的是搜狐的镜像源:http://mirrors.sohu.com/python/3.6.2/
  • 要选择扩展名是.tar.xz的包
  • 每个包都有对应的.asc文件,用来验证安装包的完整性。推荐使用 python 官方安装源中对应的.asc文件。文件很小。
  • 也可以使用 md5 验证。python 3.6.2 官网md5值列表在页面最下方的表格中。我们下载的是xz压缩格式的安装包,所以应该查看XZ compressed source tarball所对应的 md5 值,与在本地安装包计算出 md5 值对比即可

2. 把Python-3.6.2.tar.xz放到目录$PYENV_ROOT/sources/3.6.2

  • $PYENV_ROOT需要用具体的绝对路径替换。可通过echo $PYENV_ROOT命令查看
  • sources目录下,需要创建以版本号命名的子目录。比如现在是 3.6.2 版本,就创建名为"3.6.2"的子目录。如果是 2.7.13 版本,就创建名为"2.7.13"的子目录
  • 步骤 1 中选择.tar.xz包的原因是 pyenv 只检测这种包。(我之前下载的是tgz格式的,pyenv就完全没有检测到,依然从默认源下载😂)

3. 在终端中运行 pyenv install 3.6.2 -k

  • -k/--keep参数,就是先检测本地是否已有安装包,如果有就不用从服务器上下载了。具体说明可以参考 pyenv 的帮助pyenv install --help
  • 在我的Mac上安装过程稍微有些慢,可能是老机子的缘故吧

4. 顺利安装成功,Enjoy!

部分参考

  1. 阿里云 pyenv 无法下载 python
  2. Python 官方源
  3. 搜狐镜像源

几种常见排序算法的JavaScript实现

目录

就 JavaScript 而言,Array 对象有方法sort()可以对数组成员进行排序,默认是字典顺序。自定义排序规则需要给sort()方法提供一个函数。此函数本身有2个参数,表示进行比较的两个元素。如果返回值大于0,表示第1个元素在后面,其他情况下第1个元素在前面。

下面时其他排序算法的代码,扩充 Array 的排序功能。

稳定的排序

冒泡排序

时间复杂度是O(n2)

代码如下:

Array.prototype.bubbleSort = function() {
  var len = this.length
  var temp = 0
  while (len) {
    for (var i = 1; i < len; i++) {
      if (this[i-1] > this[i]) { //升序排列
        temp = this[i-1]
        this[i-1] = this[i]
        this[i] = temp
      }
    }
    len--
  }
}

插入排序

时间复杂度是O(n2)

代码如下:

Array.prototype.insertionSort = function() {
  var i, j, temp
  var len = this.length
  for (i = 1; i < len; i++) {
    temp = this[i]  //无序区的第一个元素
    for (j = i - 1; j >= 0 && this[j] > temp; j--)
      this[j+1] = this[j]
    this[j+1] = temp
  }
}

可以视为将数组分成两个区域:(有序区,无序区)

过程:把无序区的第一个元素插入到有序区的合适的位置。

操作:比较得少,换得多。

归并排序

时间复杂度是O(n log n);需要O(n)额外空间

代码如下:

Array.prototype.mergeSort = function() {
  //合并
  var merge = function(left, right) {
    var final = []
    while (left.length && right.length)
      final.push(left[0] <= right[0] ? left.shift() : right.shift())
    return final.concat(left.concat(right))
  }
  //递归分块
  var len = this.length
  if (len < 2) return this
  var mid = len >> 1
  return merge(this.slice(0,mid).mergeSort(),this.slice(mid).mergeSort())
}

不稳定的排序

选择排序

时间复杂度是O(n2)

代码如下:

Array.prototype.selectionSort = function() {
  var i, j, min, temp
  var len = this.length
  for (i = 0; i < len - 1; i++) {
    min = i
    for (j = i + 1; j < len; j++)
      if (this[min] > this[j]) min = j
    temp = this[min]
    this[min] = this[i]
    this[i] = temp
  }
}

将数组分为两个部分:(有序区,无序区)

过程:在无序区里找一个最小的元素跟在有序区的后面

操作:比较得多,换得少。

希尔排序

时间复杂度是O(n log2 n) (log n)的平方 略差于比较算法的 O(n log n)。

也称递减增量排序算法,是插入排序的一种更高效的改进版本,通过将待比较的元素分成几个区域来提升插入排序的性能。(插入排序对于接近排好的数据进行操作时效率很高,可达到线性)

→ 关键在于步长的选择。

代码如下:

Array.prototype.shellSort = function() {
  var gap, i, j, temp
  var len = this.length
  for (gap = len >> 1; gap > 0; gap >>= 1) //步长折半
    for (i = gap; i < len; i++) {
      temp = this[i]
      for (j = i - gap; j >= 0 && this[j] > temp; j -= gap)
        this[j + gap] = this[j]
      this[j + gap] = temp
    }
}

堆排序

时间复杂度为O(n log n)

代码如下:

Array.prototype.heapSort = function() {
  var arr = this.slice(0)
  function swap(i, j) { //封装交换操作
    var temp = arr[i]
    arr[i] = arr[j]
    arr[j] = temp
  }
  function max_heapify(start, end) { //最大堆调整。使得根节点为堆的最大值
    var dad = start
    var son = dad * 2 + 1
    if (son >= end) return //递归终止条件
    if (son + 1 < end && arr[son] < arr[son + 1]) son++ //选择左右子节点中的大者
    if (arr[dad] <= arr[son]) {
      swap(dad, son)
      max_heapify(son, end)
    }
  }
  var len = arr.length
  //初始化,i从最后一个父节点开始往前调整。最终数组第一个元素为最大值
  for (var i = (len >> 1) - 1; i >= 0; i--) max_heapify(i, len)
  //把堆顶元素交换到末位(进入有序区),然后剩余元素再次进行调整,直至排序结束
  for (var i = len - 1; i > 0; i--) {
    swap(0, i)
    max_heapify(0, i)
  }
  return arr
}

可把数组看作2部分:(最大堆,有序区)

过程:从堆顶把根卸出来放在有序区之前,然后在调整最大堆。

快速排序

时间复杂度为平均O(n log n),最坏O(n2)。适合于大的、随机数列表。

代码如下:

Array.prototype.quickSort = function() {
  var len = this.length
  if (len <= 1) return this.slice(0)
  var left = []
  var right = []
  var mid = [this[0]]
  for (var i = 1; i < len; i++)
    if (this[i] < mid[0])
      left.push(this[i])
    else
      right.push(this[i])
  return left.quickSort().concat(mid.concat(right.quickSort()))
}

参考:

排序算法 - 维基百科

GitHub风格的MD语法

慕课网AngularJS实战课程笔记(ng1)

目录

基础概念

前端框架与前端类库

  • 类库:函数集合。其内容是封装一些实现复杂功能的或可复用的代码,目的是提高编码工作的效率。举例:jQuery, GreenSock(JS动画库),mootools(JS API封装库),zeptojs(移动端jQuery)……

参考:常用JavaScript类库与框架总结

补充:JavaScript全栈开发必备工具

  • 框架:一种设计模式或几种模式组合的体现。改变以DOM操作为核心的前端工作流,向后端工作方式靠拢。针对某些领域或场景提供完整解决方案,提高开发效率。举例:AngularJS,React,Vue.js……

AngularJS 1.x 四大特性

①MVC
②模块化(依赖注入,服务)
③指令
④双向数据绑定

前端开发环境/工具组合

  • 代码编辑:sublime、webstorm
  • 断点调试:浏览器开发者工具、batarang(AngularJS定制)
  • 版本管理:git
  • 代码合并压缩混淆:grunt,gulp
  • 依赖管理:bower,npm
  • 单元测试:Karma(容器)+Jasmine(测试语法)
  • 集成(e2e)测试:protractor
  • 轻量级服务器:http-server(基于node.js的HTTP接口)

核心:node.js

参考:

开发工具等综合性资源!!!

AngularJS端到端测试

Controller

ng的MVC结构

  • 一个Controller控制一小块View(单一功能)
  • 在Controller中不操作DOM(在指令中操作)
  • 在Controller中不做数据过滤或格式化($filter服务、表单控件)
  • Controller彼此不会调用,通过scope的继承或事件机制通信
  • Controller不继承,复用的代码写进服务(Service/Provider/factory...)

模块

项目结构

  • HTML:引入资源文件的index.html和放模板html代码的文件夹
  • CSS:单独文件夹
  • 图片等资源:单独文件夹
  • framework文件夹:angular.js等引入的框架
  • JS:module创建注入和配置(app.js),controller创建和配置(controllers.js),指令(directives.js),过滤器(filters.js),服务(services.js),路由(routes.js)
  • 依赖管理(包、配置文件……)
  • 测试(单元、端到端)

模块划分

一个总的app模块为入口,controller、directives、services、routes、filters分别放一个模块中。app模块依赖这些模块

指令

核心配置项(config)

  • restrict(匹配模式):Attribute Element coMment Class (AEMC
  • template(HTML模板代码):"HTML代码"
  • templateUrl:"HTML模板文件的地址"
    //模板缓存服务$templateCache,可在多个指令内使用同一个模板
  • 模板替换方式
    • replace: true,替换指令(包括本身和子元素)
    • transclude: true,保留指令子元素的内容。需要template中用ng-transclude属性指定接收内容的元素

指令的运行(加载→编译→链接)

  • 编译compile:function(elem,attrs,transclude){...} //一般不写
  • 链接link: function(scope, elem, attrs, contrller){...}
  • compilelink同时存在,以compile为主,link失效
  • compilelink的区别:
    • compile:对指令的模板进行转换
    • link:在model和view之间建立关联,注册监听事件。监控model的变化:$scope.$watch('变量名',回调) 注意“防抖动”:使用$timeout服务延迟发送
    • 在link阶段scope才绑定,在compile阶段不能操作scope
    • 同一指令多个实例,compile只执行一次,link每个实例都执行一次

交互

  • 指令与controller:scope.函数。scope.$apply(函数/Angular表达式)
  • 指令之间:配置项scope、controller、require ​

独立scope

  • 配置项scope取值为空对象({}
  • 绑定策略:{ 变量名:绑定策略}
    • @:字符串变量的双向绑定
    • =:对象变量的双向绑定
    • &:在指令中绑定父级scope的函数

内置指令(官方文档)

a、form、各式input、ngInclude、script

指令库

angular-ui

服务

$http服务:$http({配置对象}).success(function).error(function)(promise风格)

自定义Service注意:①命名不要用'$'开头②注入时系统在前,自定义在后

特性:

①服务是单例的

②注入机制:先由$injector实例化

③存在于整个应用的生命周期(可用来共享数据)

Service、Factory、Provider、Constant、Value本质上都是Provider,而语法上有差异。

数据格式化专用服务:$filter。内置格式化方式,也可以自定义。

路由

原生:ng-route

扩展插件:ui-router,可以嵌套

  • 子模板指令 ui-view
  • 状态指令 ui-sref

嵌套:状态可以有子状态。用点标记:父状态.子状态

表单

Angular表格插件:ng-grid

form指令

扩展form元素:允许嵌套、自动校验、防止重复提交

给input增加type属性(HTML5更多)

添加4个css类样式

AngularJS表单基础

AngularJS Form 进阶:远程校验和自定义输入项

双向数据绑定

$scope——树

根:$rootScope,每个模块只有一个。

子scope可以继承父scope的属性和方法。

传播事件:

  • $emit(),向上(根)
  • $broadcast(),向下(包含兄弟)

scope对象:

  • 属性(在scope构造函数中添加):内部id……
  • 方法(在prototype中):$new、$watch、$digest、$eval……

$eval调用$parse服务解析计算内嵌Angular表达式

$digest机制——对象深比较:缓存上一次对象的全部值,与新对象逐一比较

不适合树型结构(对象嵌套对象),性能差。

数据绑定关键点:

  • 观察者模式:一个Model绑定多个View
  • 判断Model是否变化:脏值检查遍历$watch列表,有变化应用就进入$digest循环,直到值不再变化就应用新值,继续遍历$watch列表。遍历完成时即Model稳定,再更新View
  • 判断深层嵌套的Model某属性是否变化,对象深比较
  • A、B两方法互相watch,避免“振荡”——TTL:连续检测到10次(阈值)就停止监听并报错

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.