diff --git a/404.html b/404.html index e1260242..c5de60e7 100644 --- a/404.html +++ b/404.html @@ -131,7 +131,7 @@ @@ -139,14 +139,14 @@ @@ -384,7 +384,7 @@

Hadoop面经总结

本文主要收集大数据Hadoop相关知识点总结。

HDFS总结

介绍一下HDFS的NameNode和DataNode

主节点NameNode:掌管文件系统目录树,处理客户端读写请求,负责管理整个文件系统的元数据,负责维持文件的副本数量

SecondaryNameNode:主要是给NameNode分担压力,把NN的fsimage和edit log做定期融合,融合后传给NN,以确保备份到的元数据是最新的,是冷备。

从节点DataNode:存储整个集群所有数据块,处理真正的数据读写,通过心跳信息定期地向NameNode汇报自身保存的文件块信息

NameNode如何保证高可用

搭建Hadoop HA集群,通过多个NameNode实现集群中NameNode的热备,解决单点故障问题,保证高可用。在任何时候,要确保NameNode只有一个处于Active状态,其他处于Standby状态。

在高可用配置下,edit log不在存放在SecondaryNameNode,而是存放在QJM(quorum journal manager)共享存储系统中,Standby NameNode监听这个共享存储系统,发现新数据写入,则读取数据并且加载到自己内存中,确保自己的内存状态和Active NameNode保持一致。

HDFS为什么不适合存储小文件

  1. 数据的元信息存储在NameNode内存中,但是NameNode的内存和存储block数目是有限的。一个block元信息消耗大约150byte内存,存储一亿个block,会需要20GB内存。
  2. 相比于存取同等大小的一个大文件,存取大量小文件会消耗大量的寻道时间

Hadoop心跳机制

  1. Hadoop是主从架构,Master有NameNode和ResourceManager,Slave有DataNode和NodeManager。
  2. Master启动时会启动一个IPC Server(进程间通信服务),等待Slave的连接。
  3. Slave启动时,主动连接Master的IPC Server,每隔3s连接一次。Slave通过心跳汇报自己的信息,Master通过心跳给Slave下达命令。
  4. HDFS默认的超时时间为10min+30s,当超过这个时间还没有心跳,则认为节点宕机。其中10min为2次心跳重试间隔时间(5min),30秒为10次心跳间隔时间(3s)。

Hadoop正常启动时进入安全模式的原因

  1. NameNode的内存元数据中,包含文件路径、副本数、blockid、每一个block所在的DataNode的信息。但是在NameNode启动时,元数据从fsimage中加载,没有每一个block所在的DataNode的信息。
  2. NameNode认为block丢失,block丢失率超过0.1%即进入安全模式。
  3. DataNode启动后,通过心跳机制汇报自身持有的blockid信息,NameNode接受心跳,会将内存元数据中的每一个block所在的DataNode的信息补全,找到所有block位置后,退出安全模式。
]]> @@ -37,10 +37,10 @@ - - + + @@ -48,7 +48,7 @@ https://www.awebone.com/posts/e3c0f347/ 2020-03-29T07:00:00.000Z - 2020-03-31T15:19:08.633Z + 2020-03-31T15:20:38.547Z

常用排序算法总结

本文对常用排序算法进行总结。

]]>
@@ -61,10 +61,10 @@ - - + +
@@ -72,7 +72,7 @@ https://www.awebone.com/posts/dd22b276/ 2020-03-26T07:00:00.000Z - 2020-03-31T15:18:39.751Z + 2020-03-31T15:20:38.546Z

多种计算引擎实现WordCount

本文使用多种计算引擎实现词频统计。

MapReduce实现

编写MapReduce程序分成三部分:MapperReducerDriver

业务逻辑

  1. MapTask阶段处理每个数据分块的单词统计分析,每遇到一个单词,将其转换为一个k-v对,如<hello, 1>的形式,发送给ReduceTask进行汇总
  2. ReduceTask阶段接受MapTask的结果,做汇总计数

Mapper接受的四个泛型

  • KEYIN:输入的键的类型,在这里指的是每一行起始的偏移量
  • VALUEIN:输入的值的类型,在这里指的是一行的内容
  • KEYOUT:输出的键的类型,这里指的是单词,允许重复的
  • VALUEOUT:输出的值的类型

Reducer接受的四个泛型

  • KEYIN:map输出的key,指的就是单词
  • VALUEIN:map输出的value,指的就是1

  • KEYOUT:输出的key的类型,这里指的就是单词,这里的key不可以重复

  • VALUEOUT:输出的value的类型,这里指的就是总的词频

Hadoop中自定义的序列化和反序列化的接口

Java中的序列化和反序列化接口Serializable,将类结构一并进行序列化和反序列化,过于臃肿

  • long——LongWritable
  • int——IntWritable
  • double——DoubleWritable
  • float——FloatWritable
  • null——NullWritable
  • string——Text

Map实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
static class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
/**
* 这个方法的调用频率:每行调用一次,文本中有几行就调用几次
* key:当前行的起始偏移量
* value:当前行的内容,和key是一一对应的
*/
@Override
protected void map(LongWritable key,
Text value,
Context context)
throws IOException, InterruptedException {
//拿到每一行的内容 进行分割
//将text---String
String line = value.toString();
//拆分单词
String[] words = line.split("\t");
//循环遍历每一个单词 进行打标机 1 发送给reduce进行统一统计
for(String w:words){
//参数1:key 参数2:value
//String--text
Text k=new Text(w);
IntWritable v=new IntWritable(1);
context.write(k, v);
}
}
}

Reduce实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
/**
* 这个方法的调用频率:每组调用一次
* 分组规则:key相同的为一组
* key:reduce输入的,这里指的是单词,每一组中的一个key
* values:每一组中的所有value,<1,1,1>
*/
@Override
protected void reduce(Text key,
Iterable<IntWritable> values,
Context context) throws IOException, InterruptedException {
//进行词频统计
int sum=0;
//循环变遍历values 求和
for(IntWritable v:values){
//v.get() 这个是将intwritable转换为int
sum+=v.get();
}
context.write(key, new IntWritable(sum));
}
}

Driver实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class Driver {
public static void main(String[] args)
throws IOException, ClassNotFoundException, InterruptedException {
System.setProperty("HADOOP_USER_NAME", "hadoop");
//加载配置文件
Configuration conf=new Configuration();
//启动一个job:一个map reduce程序,这里叫做一个job
Job job=Job.getInstance(conf);
//ָ指定job运行的主类
job.setJarByClass(Driver.class);
//指定这个job的mapper类和reduce类
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
//指定map的输出的key和value的类型
//这里为什么还要指定:泛型的只在编译的时候有作用,运行会自动擦除,所以在这里需要指定一下
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//指定reduce输出的key和value类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//指定combiner组件
//job.setCombinerClass(WordCountReducer.class);
//添加自定义分区
//job.setPartitionerClass(MyPartitioner.class);
// 这个参数如果不指定,默认reducetask=1
job.setNumReduceTasks(4);
//传参方式
//FileInputFormat.addInputPath(job, new Path(args[0]));
//添加输出路径:输出路径一定不能存在,怕如果存在会进行覆盖
//FileOutputFormat.setOutputPath(job, new Path(args[1]));
//固定写死
FileInputFormat.addInputPath(job, new Path("hdfs://hadoop01:9000/in"));
FileOutputFormat.setOutputPath(job, new Path("hdfs://hadoop01:9000/out"));
//提交job
job.waitForCompletion(true);
}
}

Scala实现

定义数据:array = Array("a b", "c c", "b c")

第一种方式实现

1
2
3
4
5
6
7
val countWord = array.flatMap(_.split(" "))
.map((_,1))
.groupBy(_._1)
.map( x => (x._1, x._2.length))
.toList
.sortBy(_._2)
.reverse

中间结果详解

  • array.map(_.split(" "))输出:Array(Array("a","b"), Array("c","c"), Array("b","c"))
  • 使用flatMap(_.split(" "))输出:Array("a","b", "c","c", "b","c")
  • 再使用map((_,1))输出:Array((a,1), (b,1), (c,1), (c,1), (b,1), (c,1))
  • 再使用groupBy(_._1)输出:(a,1),(b,1),(b,1),(c,1),(c,1),(c,1),即Map(b -> Array((b,1), (b,1)), a -> Array((a,1)), c -> Array((c,1), (c,1), (c,1)))
  • 在进行计数:array.flatMap(_.split(" ")).map((_,1)).groupBy(_._1).map( x => (x._1, x._2.length))
  • 从大到小排序:array.flatMap(_.split(" ")).map((_,1)).groupBy(_._1).map( x => (x._1, x._2.length)).toList.sortBy(_._2).reverse

其他方式实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
val countWord1 = array.map(_.split(" "))
.flatten
.map((_,1))
.groupBy(_._1)
.map(t => (t._1,t._2.size))
.toList
.sortBy(_._2)
.reverse
val countWord2 = array.flatMap(_.split(" "))
.map((_,1))
.groupBy(_._1)
.mapValues(_.size)
.toList
.sortBy(_._2)
.reverse
val countWord3 = array.flatMap(_.split(" "))
.map((_,1))
.groupBy(_._1)
.mapValues(_.foldLeft(0)(_+_._2))
.toList
.sortBy(_._2)
.reverse

Spark-shell实现

第一种方式实现

1
2
3
4
5
sc.textFile("hdfs://myha/spark/wc/input/words.txt")
.flatMap(_.split(" "))
.map((_, 1))
.reduceByKey(_+_)
.collect

详解

  • scSparkContext对象,该对象是提交spark程序的入口
  • textFile("hdfs://myha/spark/wc/input/words.txt")是从HDFS中读取数据
  • flatMap(_.split(" "))map再压平
  • map((_,1))将单词和1构成元组
  • reduceByKey(_+_)按照key进行reduce,并将value累加
  • saveAsTextFile("hdfs://myha/spark/wc/output")将结果写入到HDFS
  • 其中:reduceByKey = groupByKey + reduce = groupBy + reduce = groupBy + map

其他方式实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sc.textFile("hdfs://myha/spark/wc/input/words.txt")
.flatMap(_.split(" "))
.map((_,1))
.reduceByKey(_+_)
.collect
.foreach(println)
sc.textFile("hdfs://myha/spark/wc/input/words.txt")
.flatMap(_.split(" "))
.countByValue
.foreach(println)
sc.textFile("hdfs://myha/spark/wc/input/words.txt")
.flatMap(_.split(" "))
.map((_,1))
.countByKey()
.foreach(println)
]]>
@@ -86,34 +86,10 @@ - - -
- - - 算法学习 - - https://www.awebone.com/posts/800507c2/ - 2020-03-21T07:00:00.000Z - 2020-03-25T15:38:39.779Z - -

算法学习

数组和链表

1585056480939

1585056511253

1585056580300

1585056748131

15850568897611585056969448

1585056969448

1585057395924

1585057420437

堆栈和队列

1585057557427

1585057617265

1585057698739

1585058301980

1585058723214

优先队列

1585058974694

1585059046220

1585059134581

15850595851501585061195273

1585061195273

1585061254454

Map和set

1585061567210

1585061666508

1585061724790

1585061856478

1585061932568

1585062074692

1585062360667

1585062384433

1585062402857

1585062640205

1585063037475

1585063051531

1585063206975

]]>
- - - - <h1 id="算法学习"><a href="#算法学习" class="headerlink" title="算法学习"></a>算法学习</h1><p>数组和链表</p> - - - - - - - -
@@ -185,16 +161,16 @@ https://www.awebone.com/posts/75c6e52f/ 2019-03-17T07:00:00.000Z - 2020-03-31T13:42:22.685Z + 2020-04-01T01:58:59.099Z -

MySQL基本使用

修改mysql提示符

修改提示符的两种方式:

  1. 连接客户端时通过参数指定:shell>mysql -uroot -proot –prompt 提示符
  2. 连接上客户端后,通过prompt修改:mysql>prompt 提示符

修改参数:

\D 完整日期
\d 数据库
还可以搭配一起+符号
\h 服务器
\u 用户

mysql常用命令

系统查看:

VERSION(); 当前数据库版本
NOW();当前系统时间
USER(); 当前登录的用户

mysql语句的规范:

  1. 关键字与函数名称全部大写
  2. 数据库名称、表名称、字段名称全部小写
  3. SQL语句必须以分号结尾

数据库相关语句

成功安装后默认会带4个数据库;{}代表必选项;”|”代表从这里面做选择;中括号[]代表有或没有都可以,可选项。

  • 查看所有数据库

    SHOW DATABASES;

  • 查看所有警告

    SHOW WARNINGS;

  • 查看数据库创建时的信息

    SHOW CREATE DATABASE db_name(数据库名);

  • 新建数据库

    CREATE {DATABASE|SCHERMA}[IF NOT EXISTS] db_name [DEFAULT] CHARACTER SET = charset_name

    如:新建数据库并设置格式

    CREATE DATABASE IF NOT EXISTS db_name [DEFAULT] (default可省略)CHARACTER SET utf-8(格式,默认utf-8,可以改为任意的);

  • 修改数据库

    ALTER {DATABASE|SCHEMA}[db_name][DEFAULT] CHARACTER SET charset_name;

    如果需要修改编码格式,可写:

    ALTER DATABASE db_name CHARACTER SET = uft8;

  • 删除数据库

    DROP {DATABASE|SCHEMA}[IF EXISTS] db_name;

表相关语句

  • 打开某个数据库

    USE db_name;

  • 查看用户当前所打开的数据库

    SELECT DATABASE();

  • 创建数据表(如果数据表已存在,加上if not exists,系统将不提示错误,否则会提示错误)

    CREATE TABLE[IF NOT EXISTS] table_name(colume_name data_type);

    列名称:经过分析得到

    数据类型:整型,浮点型等

    注意:逗号是两个字段之间的分隔符,最后一个字段不需要加逗号。

    例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    /*打开要创建表的数据库*/
    USE 数据库名;
    /*在打开的数据库中创建表*/
    CREATE TABLE tb1(
    username VARCHAR(20),
    age TINYINT UNSIGNED,
    salary FLOAT(8,2) UNSIGNED
    );
  • 显示当前数据库的表

    SHOW TABLES;

  • 显示mysql库中的表

    SHOW TABLES FROM mysql;

    注:但是并没有改变当前数据库,只是显示了一次其他数据库的列表

  • 查看数据表结构

    SHOW COLUMNS FROM table_name;

  • 插入数据

    INSERT [INTO] tb_name(表名) [col_name,....](表里的哪几列要赋值,可省略) VALUES(val,...)(值是多少)

    如果省略列的名称,必须给所有字段赋值,否则会报错。

  • 查询全表

    SELECT * FROM tb1;

创建表时需要注意的字段控制

字段是否为空

NULL:字段值可为空

NOT NULL:字段值不为空

同一个字段不可能既为NULL,又为NOT NULL

在创建数据表的时候,如果字段值可为空,可以写NULL,也可省略,不写的话默认为空,如果为空可赋值也可不赋值

1
2
3
4
CREATE TABLE tb2(
username VARCHAR(20) UNSIGNED NOT NULL,
age TINYINT UNSIGNED NULL
);

字段是否自增

字段为数值型时可为整数或浮点数,为浮点数时小数位必须要为0,如:FLOAT (7,0)

AUTO_INCREMENT:自动编号,必须与主键组合使用,否则会报错,默认情况下,起始值为1,每次的增量为1,保证记录唯一性

AUTO_INCREMENT必须和PRIMARY KEY 一起使用,每次自增1,可不进行赋值

PRIMARY KEY 可以不和AUTO_INCREMENT一起使用,可以被赋值但是不允许有相同值的出现

1
2
3
4
CREATE TABLE tb3(
id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(20) UNSIGNED NOT NULL
);

字段是否唯一

unique key:唯一约束

唯一约束可以保证记录的唯一性

唯一约束的字段可以为空值(null),即使存储多个值,最终保留的空值也只有一个,故可以保证唯一性。

每张数据表可以存在多个唯一约束,可以存在多个空值null,primary key就只有1个。

唯一约束添加语句:username varchar(20) not null unique key

达到的效果就是如果插入语句有相同的字段,那么会约束它,只能保证数据唯一性。

primary keyunique key的区别

primary keyunique key都是唯一性约束,但二者有很大的区别:

  1. 作为primary key的1个或多个列必须为NOT NULL,而unique key约束的列可以为null,这是primary keyunique key最大的区别。
  2. 一个表只能有一个primary key(单列或多列,多列主键叫联合主键),但可以有多个unique key

默认值设置

default 设置:当插入记录时,如果没有明确为字段赋值,则自动赋予默认值

sex enum('1','2','3') default '3'

这个语句要达成的效果就是性别提供三个选项:1男,2女,3保密,那么如果数据插入没有添加性别,那么默认为3选项

数据类型

字符型

mysql_char

整型

mysql_int

浮点型

mysql_float

日期时间型

mysql_data

数据表操作:插入几录 查找记录
记录操作:创建数据表 约束的使用

create table table_name 创建数据表
show columns from table_name查看数据表结构
select*from table_name数据查找,验证数据是否成功写入。

auto_increment必须要和主键一起使用 但是主键可以不和auto_increment一起使用 不一起使用时主键可以自主赋值
PRIMARY KEY 主键约束 一张表只能有一个主键约束
Unique key 唯一约束 一个表可以有多个Unique约束
default 默认约束

具有外键列的表称为子表;子表所参照的表称为父表
1.父表和子表必须使用相同的存储引擎,而且禁止使用临时表
2.数据表的存储引擎只能为InnoDB
3.外键列和参照列必须具有相似的数据类型,其中数字的长度或是否有符号位必须相同;而字符的长度则可以不同
4.外键列和参照列必须创建索引,如果参照列不存在索引的话,mysql将自动创建索引;如果外键列没有索引,mysql将不会自动创建索引(此处根据语音修改,与PPT内容不一致——经查,mysql5.5以上的版本不会自动创建外键索引,但根据实际情况,创建外建索引很有必要。)

表级约束:约束只针对某一字段
列级约束:约束针对两个及两个以上字段
FOREIGN KEY(外键约束):保持数据的一致性,完整性。实现数据表的一对一,一对多的关系。
1,父表(子表所参照的表)和子表(具有外键列的表)必须使用相同的存储引擎,而且禁止使用临时表。
2,数据表的存储引擎只能为InnoDB(可在my.ini查看修改。5.7版本my.ini地址:C:\ProgramData\MySQL\MySQL Server 5.7\my.ini)。
3,外键列(曾经加过foreign关键词的那一列)和参照列(外键列所参照的那列)必须具有相似的数据类型(字符,整型,日期时间等)。其中数字的长度或是否有符号位(如整型有无符号(unsigned)和有符号(signed)两种类型;)必须相同;而字符的长度则可以不同。比如说父表里面有一个参数id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,子表里面就要写作pid SMALLINT UNSIGNED(符号位和数据类型要相似)
4,外键列和参照列必须创建索引。如果外键列不存在索引的话,MySQL将自动创建索引。
FOREIGN KEY (pid)REFERENCES 父表名(id)
也就是users表中有两个索引(id pid)
外键列:pid (可自定义)
参照列:id (可自定义)
SHOW INDEXES FROM table_name查看索引
SHOW INDEXES FROM table_name\G;以网格方式来查看索引

外键约束的参照操作:
在实际的项目开发中,为避免受引擎限制,通常使用逻辑外键约束,而不使用此物理的外键约束(按照外键的定义来设计数据表,但不使用FOREIGN KEY)。
1.CASCADE从父表删除或更新时自动删除或更新子表中的匹配行
2.SET NULL从父表删除或更新行时,设置子表中的外键列为NULL。如果使用该选项,必须保证子表列没有指定NOT NULL
3.RESTRICT拒绝对父表的删除或更新操作
4.NO ACTION标准的SQL关键字,在mysql中与RESTRICT作用相同

对于一个列所创建的约束,称之为列级约束。
而对于两个或两个以上的列所创建的约束,我们称之为表级约束。
列级约束在使用时,既可以在列定义的时候声明,也可以在列定义以后声明,而表级的约束只能在列定义以后来声明。
在实际开发中,用列级约束比较多,表级约束很少用,
在所有的约束中,并不是说每种约束都存在着表级或列级约束,其中,NOT NULL 非空约束,DEFAULT约束这两种约束就不存在表级约束,它们只有列级约束,而对于其他的三种,像主键,唯一,外键,它们都可以存在表级和列级约束。

删除列:ALTER TABLE tb1_name DROP[COLUMN] col_name;
添加多列:ALTER TABLE tb1_name ADD[COLUMN] (col_name column_definition,…);
添加单列:ALTER TABLE tb1_name ADD[COLUMN] col_name column_definition [FIRST|AFTER col_name];
删除记录:DELETE FROM province WHERE id=3;
验证表中是否有相应的记录:SELECT * FROM province;
显示索引:SHOW INDEXES FROM province;SHOW INDEXES FROM province\G;(以网格呈现)
打开数据表test:USE test;
查看创建命令:SHOW CREATE TABLE province;
查看数据表结构:SHOW COLUMNS FROM tb3;
插入记录:INSERT [INTO] tb1_name [(col_name,…)] VALUES (val,…);
查看数据表列表:SHOW TABLES [FROM db_name] [LIKE ‘pattern’|WHERE expr];
添加的单列将他至于那一列后面语句:after 后面跟要添加其下的列名
alter table users1 add 要添加的列名 varchar(32) not null after 列名;
将添加的单列位于所有列之前:first
alter table users1 add 要添加的列名和属性 first;
多个操作可以同时操作,用逗号分开

增加一行
ALTER TABLE tb_name ADD age SMALLINT UNSIGNED NOT NULL;
添加主键约束(只能添加一个)
ALTER TABLE tbl_name ADD [CONSTRAINT [symbol自定义的约束的名称]] PRIMARY KEY [index_type] (index_col_name,…)
ALTER TABLE tb_1 ADD PRIMARY KEY(id);
添加唯一约束(可以添加多个)
ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] UNIQUE [index_type] (index_col_name,…)
ALTER TABLE tb_1 ADD UNIQUE (username);
添加外键约束
ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_type] (index_col_name,…)
reference_definition
例:ALTER TABLE t3 ADD FOREIGN KEY (age)REFERENCES t2(age);
添加/删除默认约束
ALTER TABLE tbl_name ALTER [COLUMN] col_name SET DAFAULT literal(比如age里面可设置为10,20 |DROP DEFAULT
例:ALTER TABLE user2 ALTER age SET DEFAULT 15;
ALTER TABLE user2 ALTER age DROP DEFAULT;

查索引是SHOW INDEX
查约束是SHOW INDEXES
约束和索引, 前者是用来检查数据的正确性,后者用来实现数据查询的优化,目的不同。
唯一性约束与唯一索引有所不同:
(1).创建唯一约束会在Oracle中创建一个Constraint,同时也会创建一个该约束对应的唯一索引。
(2).创建唯一索引只会创建一个唯一索引,不会创建Constraint。
也就是说其实唯一约束是通过创建唯一索引来实现的。
在删除时这两者也有一定的区别:
删除唯一约束时可以只删除约束而不删除对应的索引,所以对应的列还是必须唯一的,
而删除了唯一索引的话就可以插入不唯一的值。
删除唯一约束:ALTER TABLE table_name DROP INDEX 数据名;
PRIMARY KEY 和 KEY 的区别:
主键一定是唯一性索引,唯一性索引并不一定就是主键
一个表中可以有多个唯一性索引,但只能有一个主键
主键列不允许空值,而唯一性索引列允许空值
删除主键约束:alter table user2 drop primary key;
不用选择字段 因为一张表有也只有一个主键。
删除外键约束:alter table 数据表名 drop foreign key user_ibfk_1;
在删除之前要先找到外键名 需用show create table 数据表名;来查看

1.修改列定义
用关键字ALTER TABLE..MODIFY
ALTER TABLE tbl_name MODIFY [COLUMN] col_name column_definition [FIRST |AFTER col_name];
ALTER TABLE users2 MODIFY id SMALLINT UNSIGNED NOT NULL FIRST; //将id字段的位置提到第一列
SHOW COLUMNS FROM users2;
ALTER TABLE users2 MODIFY id TINYINT UNSIGNED NOT NULL; //修改数据类型,需注意数据丢失的问题

2.修改列名称,用CHANGE方法可以同时修改列名称和列定义.
用关键字ALTER..CHANGE
ALTER TABLE tbl_name CHANGE [COLUMN] col_name new_col_name column_definition [FIRST|AFTER col_name];
ALTER TABLE users2 CHANGE pid p_id TINYINT UNSIGNED; //修改列名称

3.更换数据表名
用关键字ALTER..RENAME
修改一个表的表名(方法1)
ALTER TABLE users2 RENAME person;
修改一个表的表名(方法2)
用关键字RENAME..TO
RENAME TABLE users5 TO users2;
一次修改多个表的表名,操作间用逗号隔开.
RENAME TABLE users5 TO users2,users3 TO users4;
应该少使用数据表的列名及表名的更名。

  1. 创建表:
    create table user(
    id smallint primary key not null auto_increment,name varchar(20),age smallint
    );
  2. show create table user; 查看创建表信息
    show tables; 显示当前数据库所有的表
    show columns from user; 显示列属性 或 discribe user;
    show indexes from user \G; 显示所有的索引,“\G” 表示按列显示
  3. drop table user1; 删除表
  4. 表添加一列: alter table user add age tinyint
    表删除一列: alter table user drop age;
  5. 添加主键约束:alter table user2 add primary key (id);
    删除主键约束:alter table user2 drop primary key;
    添加唯一约束: alter table user2 add unique key uni_key (name);
    删除唯一约束: drop index uni_key on user2;
    添加外键约束:alter table user2 add foreign key (age) references user(id);
    添加默认约束:alter table user2 alter age set default 20;
    删除默认约束:alter table user2 alter age drop default;
    修改列属性:alter table user2 modify name varchar(30);
    修改列名:alter table user2 change age age1 tinyint not null;
    修改表名:alter tabler user2 rename user3 或者 rename table user3 to user2;
    注:尽量不要修改列名和表名
]]>
+

MySQL基本使用

修改MySQL提示符

修改提示符的两种方式:

  1. 连接客户端时通过参数指定:shell>mysql -uroot -proot --prompt 提示符
  2. 连接上客户端后,通过prompt修改:mysql>prompt 提示符

修改参数:

\D 完整日期
\d 数据库
还可以搭配一起+符号
\h 服务器
\u 用户

MySQL常用命令

系统查看:

VERSION(); 当前数据库版本
NOW();当前系统时间
USER(); 当前登录的用户

MySQL语句的规范:

  1. 关键字与函数名称全部大写
  2. 数据库名称、表名称、字段名称全部小写
  3. SQL语句必须以分号结尾

数据库相关语句

成功安装后默认会带4个数据库;{}代表必选项;”|”代表从这里面做选择;中括号[]代表有或没有都可以,可选项。

  • 查看所有数据库

    SHOW DATABASES;

  • 查看所有警告

    SHOW WARNINGS;

  • 查看数据库创建时的信息

    SHOW CREATE DATABASE db_name(数据库名);

  • 新建数据库

    CREATE {DATABASE|SCHERMA}[IF NOT EXISTS] db_name [DEFAULT] CHARACTER SET = charset_name

    如:新建数据库并设置格式

    CREATE DATABASE IF NOT EXISTS db_name [DEFAULT] (default可省略)CHARACTER SET utf-8(格式,默认utf-8,可以改为任意的);

  • 修改数据库

    ALTER {DATABASE|SCHEMA}[db_name][DEFAULT] CHARACTER SET charset_name;

    如果需要修改编码格式,可写:

    ALTER DATABASE db_name CHARACTER SET = uft8;

  • 删除数据库

    DROP {DATABASE|SCHEMA}[IF EXISTS] db_name;

表相关语句

  • 打开某个数据库

    USE db_name;

  • 查看用户当前所打开的数据库

    SELECT DATABASE();

  • 创建数据表(如果数据表已存在,加上if not exists,系统将不提示错误,否则会提示错误)

    CREATE TABLE[IF NOT EXISTS] table_name(colume_name data_type);

    列名称:经过分析得到

    数据类型:整型,浮点型等

    注意:逗号是两个字段之间的分隔符,最后一个字段不需要加逗号。

    例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    /*打开要创建表的数据库*/
    USE 数据库名;
    /*在打开的数据库中创建表*/
    CREATE TABLE tb1(
    username VARCHAR(20),
    age TINYINT UNSIGNED,
    salary FLOAT(8,2) UNSIGNED
    );
  • 显示当前数据库的表

    SHOW TABLES;

  • 显示mysql库中的表

    SHOW TABLES FROM mysql;

    注:但是并没有改变当前数据库,只是显示了一次其他数据库的列表

  • 查看数据表结构

    SHOW COLUMNS FROM table_name;

  • 插入数据

    INSERT [INTO] tb_name(表名) [col_name,....](表里的哪几列要赋值,可省略) VALUES(val,...)(值是多少)

    如果省略列的名称,必须给所有字段赋值,否则会报错。

  • 查询全表

    SELECT * FROM tb1;

创建表时需要注意的字段控制

字段是否为空

NULL:字段值可为空

NOT NULL:字段值不为空

同一个字段不可能既为NULL,又为NOT NULL

在创建数据表的时候,如果字段值可为空,可以写NULL,也可省略,不写的话默认为空,如果为空可赋值也可不赋值

1
2
3
4
CREATE TABLE tb2(
username VARCHAR(20) UNSIGNED NOT NULL,
age TINYINT UNSIGNED NULL
);

字段是否自增

字段为数值型时可为整数或浮点数,为浮点数时小数位必须要为0,如:FLOAT (7,0)

AUTO_INCREMENT:自动编号,必须与主键组合使用,否则会报错,默认情况下,起始值为1,每次的增量为1,保证记录唯一性

AUTO_INCREMENT必须和PRIMARY KEY 一起使用,每次自增1,可不进行赋值

PRIMARY KEY 可以不和AUTO_INCREMENT一起使用,可以被赋值但是不允许有相同值的出现

1
2
3
4
CREATE TABLE tb3(
id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(20) UNSIGNED NOT NULL
);

字段是否唯一

unique key:唯一约束

唯一约束可以保证记录的唯一性

唯一约束的字段可以为空值(null),即使存储多个值,最终保留的空值也只有一个,故可以保证唯一性。

每张数据表可以存在多个唯一约束,可以存在多个空值null,primary key就只有1个。

唯一约束添加语句:username varchar(20) not null unique key

达到的效果就是如果插入语句有相同的字段,那么会约束它,只能保证数据唯一性。

primary keyunique key的区别

primary keyunique key都是唯一性约束,但二者有很大的区别:

  1. 作为primary key的1个或多个列必须为NOT NULL,而unique key约束的列可以为null,这是primary keyunique key最大的区别。
  2. 一个表只能有一个primary key(单列或多列,多列主键叫联合主键),但可以有多个unique key

默认值设置

default 设置:当插入记录时,如果没有明确为字段赋值,则自动赋予默认值

sex enum('1','2','3') default '3'

这个语句要达成的效果就是性别提供三个选项:1男,2女,3保密,那么如果数据插入没有添加性别,那么默认为3选项

数据类型

字符型

mysql_char

整型

mysql_int

浮点型

mysql_float

日期时间型

mysql_data

数据表操作:插入几录 查找记录
记录操作:创建数据表 约束的使用

create table table_name 创建数据表
show columns from table_name查看数据表结构
select*from table_name数据查找,验证数据是否成功写入。

auto_increment必须要和主键一起使用 但是主键可以不和auto_increment一起使用 不一起使用时主键可以自主赋值
PRIMARY KEY 主键约束 一张表只能有一个主键约束
Unique key 唯一约束 一个表可以有多个Unique约束
default 默认约束

具有外键列的表称为子表;子表所参照的表称为父表
1.父表和子表必须使用相同的存储引擎,而且禁止使用临时表
2.数据表的存储引擎只能为InnoDB
3.外键列和参照列必须具有相似的数据类型,其中数字的长度或是否有符号位必须相同;而字符的长度则可以不同
4.外键列和参照列必须创建索引,如果参照列不存在索引的话,mysql将自动创建索引;如果外键列没有索引,mysql将不会自动创建索引(此处根据语音修改,与PPT内容不一致——经查,mysql5.5以上的版本不会自动创建外键索引,但根据实际情况,创建外建索引很有必要。)

表级约束:约束只针对某一字段
列级约束:约束针对两个及两个以上字段
FOREIGN KEY(外键约束):保持数据的一致性,完整性。实现数据表的一对一,一对多的关系。
1,父表(子表所参照的表)和子表(具有外键列的表)必须使用相同的存储引擎,而且禁止使用临时表。
2,数据表的存储引擎只能为InnoDB(可在my.ini查看修改。5.7版本my.ini地址:C:\ProgramData\MySQL\MySQL Server 5.7\my.ini)。
3,外键列(曾经加过foreign关键词的那一列)和参照列(外键列所参照的那列)必须具有相似的数据类型(字符,整型,日期时间等)。其中数字的长度或是否有符号位(如整型有无符号(unsigned)和有符号(signed)两种类型;)必须相同;而字符的长度则可以不同。比如说父表里面有一个参数id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,子表里面就要写作pid SMALLINT UNSIGNED(符号位和数据类型要相似)
4,外键列和参照列必须创建索引。如果外键列不存在索引的话,MySQL将自动创建索引。
FOREIGN KEY (pid)REFERENCES 父表名(id)
也就是users表中有两个索引(id pid)
外键列:pid (可自定义)
参照列:id (可自定义)
SHOW INDEXES FROM table_name查看索引
SHOW INDEXES FROM table_name\G;以网格方式来查看索引

外键约束的参照操作:
在实际的项目开发中,为避免受引擎限制,通常使用逻辑外键约束,而不使用此物理的外键约束(按照外键的定义来设计数据表,但不使用FOREIGN KEY)。
1.CASCADE从父表删除或更新时自动删除或更新子表中的匹配行
2.SET NULL从父表删除或更新行时,设置子表中的外键列为NULL。如果使用该选项,必须保证子表列没有指定NOT NULL
3.RESTRICT拒绝对父表的删除或更新操作
4.NO ACTION标准的SQL关键字,在mysql中与RESTRICT作用相同

对于一个列所创建的约束,称之为列级约束。
而对于两个或两个以上的列所创建的约束,我们称之为表级约束。
列级约束在使用时,既可以在列定义的时候声明,也可以在列定义以后声明,而表级的约束只能在列定义以后来声明。
在实际开发中,用列级约束比较多,表级约束很少用,
在所有的约束中,并不是说每种约束都存在着表级或列级约束,其中,NOT NULL 非空约束,DEFAULT约束这两种约束就不存在表级约束,它们只有列级约束,而对于其他的三种,像主键,唯一,外键,它们都可以存在表级和列级约束。

删除列:ALTER TABLE tb1_name DROP[COLUMN] col_name;
添加多列:ALTER TABLE tb1_name ADD[COLUMN] (col_name column_definition,…);
添加单列:ALTER TABLE tb1_name ADD[COLUMN] col_name column_definition [FIRST|AFTER col_name];
删除记录:DELETE FROM province WHERE id=3;
验证表中是否有相应的记录:SELECT * FROM province;
显示索引:SHOW INDEXES FROM province;SHOW INDEXES FROM province\G;(以网格呈现)
打开数据表test:USE test;
查看创建命令:SHOW CREATE TABLE province;
查看数据表结构:SHOW COLUMNS FROM tb3;
插入记录:INSERT [INTO] tb1_name [(col_name,…)] VALUES (val,…);
查看数据表列表:SHOW TABLES [FROM db_name] [LIKE ‘pattern’|WHERE expr];
添加的单列将他至于那一列后面语句:after 后面跟要添加其下的列名
alter table users1 add 要添加的列名 varchar(32) not null after 列名;
将添加的单列位于所有列之前:first
alter table users1 add 要添加的列名和属性 first;
多个操作可以同时操作,用逗号分开

增加一行
ALTER TABLE tb_name ADD age SMALLINT UNSIGNED NOT NULL;
添加主键约束(只能添加一个)
ALTER TABLE tbl_name ADD [CONSTRAINT [symbol自定义的约束的名称]] PRIMARY KEY [index_type] (index_col_name,…)
ALTER TABLE tb_1 ADD PRIMARY KEY(id);
添加唯一约束(可以添加多个)
ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] UNIQUE [index_type] (index_col_name,…)
ALTER TABLE tb_1 ADD UNIQUE (username);
添加外键约束
ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_type] (index_col_name,…)
reference_definition
例:ALTER TABLE t3 ADD FOREIGN KEY (age)REFERENCES t2(age);
添加/删除默认约束
ALTER TABLE tbl_name ALTER [COLUMN] col_name SET DAFAULT literal(比如age里面可设置为10,20 |DROP DEFAULT
例:ALTER TABLE user2 ALTER age SET DEFAULT 15;
ALTER TABLE user2 ALTER age DROP DEFAULT;

查索引是SHOW INDEX
查约束是SHOW INDEXES
约束和索引, 前者是用来检查数据的正确性,后者用来实现数据查询的优化,目的不同。
唯一性约束与唯一索引有所不同:
(1).创建唯一约束会在Oracle中创建一个Constraint,同时也会创建一个该约束对应的唯一索引。
(2).创建唯一索引只会创建一个唯一索引,不会创建Constraint。
也就是说其实唯一约束是通过创建唯一索引来实现的。
在删除时这两者也有一定的区别:
删除唯一约束时可以只删除约束而不删除对应的索引,所以对应的列还是必须唯一的,
而删除了唯一索引的话就可以插入不唯一的值。
删除唯一约束:ALTER TABLE table_name DROP INDEX 数据名;
PRIMARY KEY 和 KEY 的区别:
主键一定是唯一性索引,唯一性索引并不一定就是主键
一个表中可以有多个唯一性索引,但只能有一个主键
主键列不允许空值,而唯一性索引列允许空值
删除主键约束:alter table user2 drop primary key;
不用选择字段 因为一张表有也只有一个主键。
删除外键约束:alter table 数据表名 drop foreign key user_ibfk_1;
在删除之前要先找到外键名 需用show create table 数据表名;来查看

1.修改列定义
用关键字ALTER TABLE..MODIFY
ALTER TABLE tbl_name MODIFY [COLUMN] col_name column_definition [FIRST |AFTER col_name];
ALTER TABLE users2 MODIFY id SMALLINT UNSIGNED NOT NULL FIRST; //将id字段的位置提到第一列
SHOW COLUMNS FROM users2;
ALTER TABLE users2 MODIFY id TINYINT UNSIGNED NOT NULL; //修改数据类型,需注意数据丢失的问题

2.修改列名称,用CHANGE方法可以同时修改列名称和列定义.
用关键字ALTER..CHANGE
ALTER TABLE tbl_name CHANGE [COLUMN] col_name new_col_name column_definition [FIRST|AFTER col_name];
ALTER TABLE users2 CHANGE pid p_id TINYINT UNSIGNED; //修改列名称

3.更换数据表名
用关键字ALTER..RENAME
修改一个表的表名(方法1)
ALTER TABLE users2 RENAME person;
修改一个表的表名(方法2)
用关键字RENAME..TO
RENAME TABLE users5 TO users2;
一次修改多个表的表名,操作间用逗号隔开.
RENAME TABLE users5 TO users2,users3 TO users4;
应该少使用数据表的列名及表名的更名。

  1. 创建表:
    create table user(
    id smallint primary key not null auto_increment,name varchar(20),age smallint
    );
  2. show create table user; 查看创建表信息
    show tables; 显示当前数据库所有的表
    show columns from user; 显示列属性 或 discribe user;
    show indexes from user \G; 显示所有的索引,“\G” 表示按列显示
  3. drop table user1; 删除表
  4. 表添加一列: alter table user add age tinyint
    表删除一列: alter table user drop age;
  5. 添加主键约束:alter table user2 add primary key (id);
    删除主键约束:alter table user2 drop primary key;
    添加唯一约束: alter table user2 add unique key uni_key (name);
    删除唯一约束: drop index uni_key on user2;
    添加外键约束:alter table user2 add foreign key (age) references user(id);
    添加默认约束:alter table user2 alter age set default 20;
    删除默认约束:alter table user2 alter age drop default;
    修改列属性:alter table user2 modify name varchar(30);
    修改列名:alter table user2 change age age1 tinyint not null;
    修改表名:alter tabler user2 rename user3 或者 rename table user3 to user2;
    注:尽量不要修改列名和表名
]]>
- <h1 id="MySQL基本使用"><a href="#MySQL基本使用" class="headerlink" title="MySQL基本使用"></a>MySQL基本使用</h1><h2 id="修改mysql提示符"><a href="#修改mysql提示符" class="headerlink" title="修改mysql提示符"></a>修改mysql提示符</h2><p><strong>修改提示符的两种方式:</strong></p> + <h1 id="MySQL基本使用"><a href="#MySQL基本使用" class="headerlink" title="MySQL基本使用"></a>MySQL基本使用</h1><h2 id="修改MySQL提示符"><a href="#修改MySQL提示符" class="headerlink" title="修改MySQL提示符"></a>修改MySQL提示符</h2><p><strong>修改提示符的两种方式:</strong></p> <ol> -<li>连接客户端时通过参数指定:shell&gt;mysql -uroot -proot –prompt 提示符</li> -<li>连接上客户端后,通过prompt修改:mysql&gt;prompt 提示符</li> +<li>连接客户端时通过参数指定:<code>shell&gt;mysql -uroot -proot --prompt</code> 提示符</li> +<li>连接上客户端后,通过<code>prompt</code>修改:<code>mysql&gt;prompt</code> 提示符</li> </ol> <p><strong>修改参数:</strong></p> <p><code>\D</code> 完整日期<br><code>\d</code> 数据库<br>还可以搭配一起<code>+</code>符号<br><code>\h</code> 服务器<br><code>\u</code> 用户</p> diff --git a/baidu_verify_3NWlza1HUZ.html b/baidu_verify_3NWlza1HUZ.html index 1f53f7a7..07837ba0 100644 --- a/baidu_verify_3NWlza1HUZ.html +++ b/baidu_verify_3NWlza1HUZ.html @@ -466,7 +466,7 @@

- 30 + 29 日志 @@ -1292,7 +1292,7 @@

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 算法学习 | Awebone's Blog - - - - - - - - - - - - - - - - - - -
-
- - - - -
-
-
-
- - -
- - - - - - - - -
- - - -
- - - - - - - -
- - - -

算法学习

- - - -
- - - - - -
- - - - - -

算法学习

数组和链表

- -

1585056480939

-

1585056511253

-

1585056580300

-

1585056748131

-

15850568897611585056969448

-

1585056969448

-

1585057395924

-

1585057420437

-

堆栈和队列

-

1585057557427

-

1585057617265

-

1585057698739

-

1585058301980

-

1585058723214

-

优先队列

-

1585058974694

-

1585059046220

-

1585059134581

-

15850595851501585061195273

-

1585061195273

-

1585061254454

-

Map和set

-

1585061567210

-

1585061666508

-

1585061724790

-

1585061856478

-

1585061932568

-

1585062074692

-

1585062360667

-

1585062384433

-

1585062402857

-

1585062640205

-

1585063037475

-

1585063051531

-

1585063206975

- - -
- - - - -
- -
- -
-------------本文结束感谢您的阅读-------------
- -
- -
- - - - - -

本文标题:算法学习

-

文章作者:Awebone

-

发布时间:2020年03月21日 - 15:03

-

最后更新:2020年03月25日 - 23:03

-

原始链接:https://www.awebone.com/posts/800507c2/ - -

-

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-
- - - -
- - - - -
-
-
- - -
- -
- - - - - -
- - - -
- - - -
- -
-
- - -
- - - - - - - - - -
- - - - - - - - - -
-
- -
- -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/posts/86ceb8f1/index.html b/posts/86ceb8f1/index.html index db520204..72a3a0d1 100644 --- a/posts/86ceb8f1/index.html +++ b/posts/86ceb8f1/index.html @@ -655,8 +655,8 @@

- @@ -740,7 +740,7 @@

- 30 + 29 日志 @@ -1582,7 +1582,7 @@

if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('/sw.js?t=1585668035970') + navigator.serviceWorker.register('/sw.js?t=1589120709179') .then(function () {console.log('ServiceWorker Register Successfully.')}) .catch(function (e) {console.error(e)}); } diff --git a/posts/8786024c/index.html b/posts/8786024c/index.html index 4fd2eccc..15db5609 100644 --- a/posts/8786024c/index.html +++ b/posts/8786024c/index.html @@ -718,7 +718,7 @@

总结 - 30 + 29 日志 @@ -1560,7 +1560,7 @@

总结if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('/sw.js?t=1585668035970') + navigator.serviceWorker.register('/sw.js?t=1589120709179') .then(function () {console.log('ServiceWorker Register Successfully.')}) .catch(function (e) {console.error(e)}); } diff --git a/posts/8c3b0bac/index.html b/posts/8c3b0bac/index.html index e4e3e0fc..f1b3a046 100644 --- a/posts/8c3b0bac/index.html +++ b/posts/8c3b0bac/index.html @@ -830,7 +830,7 @@

读取 - 30 + 29 日志 @@ -1672,7 +1672,7 @@

读取if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('/sw.js?t=1585668035970') + navigator.serviceWorker.register('/sw.js?t=1589120709179') .then(function () {console.log('ServiceWorker Register Successfully.')}) .catch(function (e) {console.error(e)}); } diff --git a/posts/948e1c93/index.html b/posts/948e1c93/index.html index 55ffab8c..469901e0 100644 --- a/posts/948e1c93/index.html +++ b/posts/948e1c93/index.html @@ -712,7 +712,7 @@

- 30 + 29 日志 @@ -1554,7 +1554,7 @@

总结 - 30 + 29 日志 @@ -1587,7 +1587,7 @@

总结if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('/sw.js?t=1585668035970') + navigator.serviceWorker.register('/sw.js?t=1589120709179') .then(function () {console.log('ServiceWorker Register Successfully.')}) .catch(function (e) {console.error(e)}); } diff --git a/posts/a79c8cf7/index.html b/posts/a79c8cf7/index.html index f60ad942..e20141b0 100644 --- a/posts/a79c8cf7/index.html +++ b/posts/a79c8cf7/index.html @@ -819,7 +819,7 @@

- 30 + 29 日志 @@ -1661,7 +1661,7 @@

- 30 + 29 日志 @@ -1545,7 +1545,7 @@

if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('/sw.js?t=1585668035970') + navigator.serviceWorker.register('/sw.js?t=1589120709179') .then(function () {console.log('ServiceWorker Register Successfully.')}) .catch(function (e) {console.error(e)}); } diff --git a/posts/bce46d0d/index.html b/posts/bce46d0d/index.html index 919dcbdc..390e6570 100644 --- a/posts/bce46d0d/index.html +++ b/posts/bce46d0d/index.html @@ -885,7 +885,7 @@

总结 - 30 + 29 日志 @@ -1727,7 +1727,7 @@

总结if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('/sw.js?t=1585668035970') + navigator.serviceWorker.register('/sw.js?t=1589120709179') .then(function () {console.log('ServiceWorker Register Successfully.')}) .catch(function (e) {console.error(e)}); } diff --git a/posts/c1c013be/index.html b/posts/c1c013be/index.html index 312ed629..5f68cf37 100644 --- a/posts/c1c013be/index.html +++ b/posts/c1c013be/index.html @@ -770,7 +770,7 @@

- 30 + 29 日志 @@ -1612,7 +1612,7 @@

- 30 + 29 日志 @@ -1608,7 +1608,7 @@

落子 - 30 + 29 日志 @@ -1558,7 +1558,7 @@

落子if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('/sw.js?t=1585668035970') + navigator.serviceWorker.register('/sw.js?t=1589120709179') .then(function () {console.log('ServiceWorker Register Successfully.')}) .catch(function (e) {console.error(e)}); } diff --git a/posts/db1de468/index.html b/posts/db1de468/index.html index 6664a24f..6ddd3183 100644 --- a/posts/db1de468/index.html +++ b/posts/db1de468/index.html @@ -684,7 +684,7 @@

- 30 + 29 日志 @@ -1526,7 +1526,7 @@

+ @@ -138,7 +138,7 @@ - + - - + + @@ -680,8 +680,8 @@

-
@@ -775,7 +775,7 @@

- 30 + 29 日志 @@ -1617,7 +1617,7 @@

if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('/sw.js?t=1585668035970') + navigator.serviceWorker.register('/sw.js?t=1589120709179') .then(function () {console.log('ServiceWorker Register Successfully.')}) .catch(function (e) {console.error(e)}); } diff --git a/posts/e20ef482/index.html b/posts/e20ef482/index.html index cff81183..ff3670a1 100644 --- a/posts/e20ef482/index.html +++ b/posts/e20ef482/index.html @@ -961,7 +961,7 @@

- 30 + 29 日志 @@ -1803,7 +1803,7 @@

+ @@ -136,7 +136,7 @@ - + @@ -600,10 +600,10 @@

- - + + @@ -710,7 +710,7 @@

- 30 + 29 日志 @@ -1552,7 +1552,7 @@

应用 - 30 + 29 日志 @@ -1668,7 +1668,7 @@

应用if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('/sw.js?t=1585668035970') + navigator.serviceWorker.register('/sw.js?t=1589120709179') .then(function () {console.log('ServiceWorker Register Successfully.')}) .catch(function (e) {console.error(e)}); } diff --git a/posts/e913391a/index.html b/posts/e913391a/index.html index acc3f49c..b331cac3 100644 --- a/posts/e913391a/index.html +++ b/posts/e913391a/index.html @@ -762,7 +762,7 @@

总结 - 30 + 29 日志 @@ -1604,7 +1604,7 @@

总结if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('/sw.js?t=1585668035970') + navigator.serviceWorker.register('/sw.js?t=1589120709179') .then(function () {console.log('ServiceWorker Register Successfully.')}) .catch(function (e) {console.error(e)}); } diff --git a/posts/fd5cbc55/index.html b/posts/fd5cbc55/index.html index 4b9dab82..6266be26 100644 --- a/posts/fd5cbc55/index.html +++ b/posts/fd5cbc55/index.html @@ -740,7 +740,7 @@

- 30 + 29 日志 @@ -1582,7 +1582,7 @@

- - - - - - Hadoop面经总结 - - /posts/1d6a9c79/ - -

Hadoop面经总结

本文主要收集大数据Hadoop相关知识点总结。

HDFS总结

介绍一下HDFS的NameNode和DataNode

主节点NameNode:掌管文件系统目录树,处理客户端读写请求,负责管理整个文件系统的元数据,负责维持文件的副本数量

SecondaryNameNode:主要是给NameNode分担压力,把NN的fsimage和edit log做定期融合,融合后传给NN,以确保备份到的元数据是最新的,是冷备。

从节点DataNode:存储整个集群所有数据块,处理真正的数据读写,通过心跳信息定期地向NameNode汇报自身保存的文件块信息

NameNode如何保证高可用

搭建Hadoop HA集群,通过多个NameNode实现集群中NameNode的热备,解决单点故障问题,保证高可用。在任何时候,要确保NameNode只有一个处于Active状态,其他处于Standby状态。

在高可用配置下,edit log不在存放在SecondaryNameNode,而是存放在QJM(quorum journal manager)共享存储系统中,Standby NameNode监听这个共享存储系统,发现新数据写入,则读取数据并且加载到自己内存中,确保自己的内存状态和Active NameNode保持一致。

HDFS为什么不适合存储小文件

  1. 数据的元信息存储在NameNode内存中,但是NameNode的内存和存储block数目是有限的。一个block元信息消耗大约150byte内存,存储一亿个block,会需要20GB内存。
  2. 相比于存取同等大小的一个大文件,存取大量小文件会消耗大量的寻道时间

Hadoop心跳机制

  1. Hadoop是主从架构,Master有NameNode和ResourceManager,Slave有DataNode和NodeManager。
  2. Master启动时会启动一个IPC Server(进程间通信服务),等待Slave的连接。
  3. Slave启动时,主动连接Master的IPC Server,每隔3s连接一次。Slave通过心跳汇报自己的信息,Master通过心跳给Slave下达命令。
  4. HDFS默认的超时时间为10min+30s,当超过这个时间还没有心跳,则认为节点宕机。其中10min为2次心跳重试间隔时间(5min),30秒为10次心跳间隔时间(3s)。

Hadoop正常启动时进入安全模式的原因

  1. NameNode的内存元数据中,包含文件路径、副本数、blockid、每一个block所在的DataNode的信息。但是在NameNode启动时,元数据从fsimage中加载,没有每一个block所在的DataNode的信息。
  2. NameNode认为block丢失,block丢失率超过0.1%即进入安全模式。
  3. DataNode启动后,通过心跳机制汇报自身持有的blockid信息,NameNode接受心跳,会将内存元数据中的每一个block所在的DataNode的信息补全,找到所有block位置后,退出安全模式。
]]> - - + + + Hadoop面经总结 + /posts/1d6a9c79/ +

Hadoop面经总结

本文主要收集大数据Hadoop相关知识点总结。

+

HDFS总结

介绍一下HDFS的NameNode和DataNode

主节点NameNode:掌管文件系统目录树,处理客户端读写请求,负责管理整个文件系统的元数据,负责维持文件的副本数量

+

SecondaryNameNode:主要是给NameNode分担压力,把NN的fsimage和edit log做定期融合,融合后传给NN,以确保备份到的元数据是最新的,是冷备。

+

从节点DataNode:存储整个集群所有数据块,处理真正的数据读写,通过心跳信息定期地向NameNode汇报自身保存的文件块信息

+ +

NameNode如何保证高可用

搭建Hadoop HA集群,通过多个NameNode实现集群中NameNode的热备,解决单点故障问题,保证高可用。在任何时候,要确保NameNode只有一个处于Active状态,其他处于Standby状态。

+

在高可用配置下,edit log不在存放在SecondaryNameNode,而是存放在QJM(quorum journal manager)共享存储系统中,Standby NameNode监听这个共享存储系统,发现新数据写入,则读取数据并且加载到自己内存中,确保自己的内存状态和Active NameNode保持一致。

+

HDFS为什么不适合存储小文件

    +
  1. 数据的元信息存储在NameNode内存中,但是NameNode的内存和存储block数目是有限的。一个block元信息消耗大约150byte内存,存储一亿个block,会需要20GB内存。
  2. +
  3. 相比于存取同等大小的一个大文件,存取大量小文件会消耗大量的寻道时间
  4. +
+

Hadoop心跳机制

    +
  1. Hadoop是主从架构,Master有NameNode和ResourceManager,Slave有DataNode和NodeManager。
  2. +
  3. Master启动时会启动一个IPC Server(进程间通信服务),等待Slave的连接。
  4. +
  5. Slave启动时,主动连接Master的IPC Server,每隔3s连接一次。Slave通过心跳汇报自己的信息,Master通过心跳给Slave下达命令。
  6. +
  7. HDFS默认的超时时间为10min+30s,当超过这个时间还没有心跳,则认为节点宕机。其中10min为2次心跳重试间隔时间(5min),30秒为10次心跳间隔时间(3s)。
  8. +
+

Hadoop正常启动时进入安全模式的原因

    +
  1. NameNode的内存元数据中,包含文件路径、副本数、blockid、每一个block所在的DataNode的信息。但是在NameNode启动时,元数据从fsimage中加载,没有每一个block所在的DataNode的信息。
  2. +
  3. NameNode认为block丢失,block丢失率超过0.1%即进入安全模式。
  4. +
  5. DataNode启动后,通过心跳机制汇报自身持有的blockid信息,NameNode接受心跳,会将内存元数据中的每一个block所在的DataNode的信息补全,找到所有block位置后,退出安全模式。
  6. +
+]]>
- - 大数据 - + 大数据 - - - - - Hadoop - - 面试 - - - -
- - - - - 常用排序算法总结 - - /posts/e3c0f347/ - -

常用排序算法总结

本文对常用排序算法进行总结。

]]>
- - + + 面试 + Hadoop + +
+ + 常用排序算法总结 + /posts/e3c0f347/ +

常用排序算法总结

本文对常用排序算法进行总结。

+ +]]>
- - 算法 - + 算法 - - - - - 面试 - - 算法 - - - -
- - - - - 多种计算引擎实现WordCount - - /posts/dd22b276/ - -

多种计算引擎实现WordCount

本文使用多种计算引擎实现词频统计。

MapReduce实现

编写MapReduce程序分成三部分:MapperReducerDriver

业务逻辑

  1. MapTask阶段处理每个数据分块的单词统计分析,每遇到一个单词,将其转换为一个k-v对,如<hello, 1>的形式,发送给ReduceTask进行汇总
  2. ReduceTask阶段接受MapTask的结果,做汇总计数

Mapper接受的四个泛型

  • KEYIN:输入的键的类型,在这里指的是每一行起始的偏移量
  • VALUEIN:输入的值的类型,在这里指的是一行的内容
  • KEYOUT:输出的键的类型,这里指的是单词,允许重复的
  • VALUEOUT:输出的值的类型

Reducer接受的四个泛型

  • KEYIN:map输出的key,指的就是单词
  • VALUEIN:map输出的value,指的就是1

  • KEYOUT:输出的key的类型,这里指的就是单词,这里的key不可以重复

  • VALUEOUT:输出的value的类型,这里指的就是总的词频

Hadoop中自定义的序列化和反序列化的接口

Java中的序列化和反序列化接口Serializable,将类结构一并进行序列化和反序列化,过于臃肿

  • long——LongWritable
  • int——IntWritable
  • double——DoubleWritable
  • float——FloatWritable
  • null——NullWritable
  • string——Text

Map实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
static class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
/**
* 这个方法的调用频率:每行调用一次,文本中有几行就调用几次
* key:当前行的起始偏移量
* value:当前行的内容,和key是一一对应的
*/
@Override
protected void map(LongWritable key,
Text value,
Context context)
throws IOException, InterruptedException {
//拿到每一行的内容 进行分割
//将text---String
String line = value.toString();
//拆分单词
String[] words = line.split("\t");
//循环遍历每一个单词 进行打标机 1 发送给reduce进行统一统计
for(String w:words){
//参数1:key 参数2:value
//String--text
Text k=new Text(w);
IntWritable v=new IntWritable(1);
context.write(k, v);
}
}
}

Reduce实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
/**
* 这个方法的调用频率:每组调用一次
* 分组规则:key相同的为一组
* key:reduce输入的,这里指的是单词,每一组中的一个key
* values:每一组中的所有value,<1,1,1>
*/
@Override
protected void reduce(Text key,
Iterable<IntWritable> values,
Context context) throws IOException, InterruptedException {
//进行词频统计
int sum=0;
//循环变遍历values 求和
for(IntWritable v:values){
//v.get() 这个是将intwritable转换为int
sum+=v.get();
}
context.write(key, new IntWritable(sum));
}
}

Driver实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class Driver {
public static void main(String[] args)
throws IOException, ClassNotFoundException, InterruptedException {
System.setProperty("HADOOP_USER_NAME", "hadoop");
//加载配置文件
Configuration conf=new Configuration();
//启动一个job:一个map reduce程序,这里叫做一个job
Job job=Job.getInstance(conf);
//ָ指定job运行的主类
job.setJarByClass(Driver.class);
//指定这个job的mapper类和reduce类
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
//指定map的输出的key和value的类型
//这里为什么还要指定:泛型的只在编译的时候有作用,运行会自动擦除,所以在这里需要指定一下
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//指定reduce输出的key和value类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//指定combiner组件
//job.setCombinerClass(WordCountReducer.class);
//添加自定义分区
//job.setPartitionerClass(MyPartitioner.class);
// 这个参数如果不指定,默认reducetask=1
job.setNumReduceTasks(4);
//传参方式
//FileInputFormat.addInputPath(job, new Path(args[0]));
//添加输出路径:输出路径一定不能存在,怕如果存在会进行覆盖
//FileOutputFormat.setOutputPath(job, new Path(args[1]));
//固定写死
FileInputFormat.addInputPath(job, new Path("hdfs://hadoop01:9000/in"));
FileOutputFormat.setOutputPath(job, new Path("hdfs://hadoop01:9000/out"));
//提交job
job.waitForCompletion(true);
}
}

Scala实现

定义数据:array = Array("a b", "c c", "b c")

第一种方式实现

1
2
3
4
5
6
7
val countWord = array.flatMap(_.split(" "))
.map((_,1))
.groupBy(_._1)
.map( x => (x._1, x._2.length))
.toList
.sortBy(_._2)
.reverse

中间结果详解

  • array.map(_.split(" "))输出:Array(Array("a","b"), Array("c","c"), Array("b","c"))
  • 使用flatMap(_.split(" "))输出:Array("a","b", "c","c", "b","c")
  • 再使用map((_,1))输出:Array((a,1), (b,1), (c,1), (c,1), (b,1), (c,1))
  • 再使用groupBy(_._1)输出:(a,1),(b,1),(b,1),(c,1),(c,1),(c,1),即Map(b -> Array((b,1), (b,1)), a -> Array((a,1)), c -> Array((c,1), (c,1), (c,1)))
  • 在进行计数:array.flatMap(_.split(" ")).map((_,1)).groupBy(_._1).map( x => (x._1, x._2.length))
  • 从大到小排序:array.flatMap(_.split(" ")).map((_,1)).groupBy(_._1).map( x => (x._1, x._2.length)).toList.sortBy(_._2).reverse

其他方式实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
val countWord1 = array.map(_.split(" "))
.flatten
.map((_,1))
.groupBy(_._1)
.map(t => (t._1,t._2.size))
.toList
.sortBy(_._2)
.reverse
val countWord2 = array.flatMap(_.split(" "))
.map((_,1))
.groupBy(_._1)
.mapValues(_.size)
.toList
.sortBy(_._2)
.reverse
val countWord3 = array.flatMap(_.split(" "))
.map((_,1))
.groupBy(_._1)
.mapValues(_.foldLeft(0)(_+_._2))
.toList
.sortBy(_._2)
.reverse

Spark-shell实现

第一种方式实现

1
2
3
4
5
sc.textFile("hdfs://myha/spark/wc/input/words.txt")
.flatMap(_.split(" "))
.map((_, 1))
.reduceByKey(_+_)
.collect

详解

  • scSparkContext对象,该对象是提交spark程序的入口
  • textFile("hdfs://myha/spark/wc/input/words.txt")是从HDFS中读取数据
  • flatMap(_.split(" "))map再压平
  • map((_,1))将单词和1构成元组
  • reduceByKey(_+_)按照key进行reduce,并将value累加
  • saveAsTextFile("hdfs://myha/spark/wc/output")将结果写入到HDFS
  • 其中:reduceByKey = groupByKey + reduce = groupBy + reduce = groupBy + map

其他方式实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sc.textFile("hdfs://myha/spark/wc/input/words.txt")
.flatMap(_.split(" "))
.map((_,1))
.reduceByKey(_+_)
.collect
.foreach(println)
sc.textFile("hdfs://myha/spark/wc/input/words.txt")
.flatMap(_.split(" "))
.countByValue
.foreach(println)
sc.textFile("hdfs://myha/spark/wc/input/words.txt")
.flatMap(_.split(" "))
.map((_,1))
.countByKey()
.foreach(println)
]]>
- - + + 算法 + 面试 + +
+ + 多种计算引擎实现WordCount + /posts/dd22b276/ +

多种计算引擎实现WordCount

本文使用多种计算引擎实现词频统计。

+

MapReduce实现

编写MapReduce程序分成三部分:MapperReducerDriver

+ +

业务逻辑

+
    +
  1. MapTask阶段处理每个数据分块的单词统计分析,每遇到一个单词,将其转换为一个k-v对,如<hello, 1>的形式,发送给ReduceTask进行汇总
  2. +
  3. ReduceTask阶段接受MapTask的结果,做汇总计数
  4. +
+

Mapper接受的四个泛型

+
    +
  • KEYIN:输入的键的类型,在这里指的是每一行起始的偏移量
  • +
  • VALUEIN:输入的值的类型,在这里指的是一行的内容
  • +
  • KEYOUT:输出的键的类型,这里指的是单词,允许重复的
  • +
  • VALUEOUT:输出的值的类型
  • +
+

Reducer接受的四个泛型

+
    +
  • KEYIN:map输出的key,指的就是单词
  • +
  • VALUEIN:map输出的value,指的就是1

    +
  • +
  • KEYOUT:输出的key的类型,这里指的就是单词,这里的key不可以重复

    +
  • +
  • VALUEOUT:输出的value的类型,这里指的就是总的词频
  • +
+

Hadoop中自定义的序列化和反序列化的接口

+

Java中的序列化和反序列化接口Serializable,将类结构一并进行序列化和反序列化,过于臃肿

+
    +
  • long——LongWritable
  • +
  • int——IntWritable
  • +
  • double——DoubleWritable
  • +
  • float——FloatWritable
  • +
  • null——NullWritable
  • +
  • string——Text
  • +
+

Map实现

+
static class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
/**
* 这个方法的调用频率:每行调用一次,文本中有几行就调用几次
* key:当前行的起始偏移量
* value:当前行的内容,和key是一一对应的
*/
@Override
protected void map(LongWritable key,
Text value,
Context context)
throws IOException, InterruptedException {
//拿到每一行的内容 进行分割
//将text---String
String line = value.toString();
//拆分单词
String[] words = line.split("\t");
//循环遍历每一个单词 进行打标机 1 发送给reduce进行统一统计
for(String w:words){
//参数1:key 参数2:value
//String--text
Text k=new Text(w);
IntWritable v=new IntWritable(1);
context.write(k, v);
}
}
}
+

Reduce实现

+
static class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
/**
* 这个方法的调用频率:每组调用一次
* 分组规则:key相同的为一组
* key:reduce输入的,这里指的是单词,每一组中的一个key
* values:每一组中的所有value,<1,1,1>
*/
@Override
protected void reduce(Text key,
Iterable<IntWritable> values,
Context context) throws IOException, InterruptedException {
//进行词频统计
int sum=0;
//循环变遍历values 求和
for(IntWritable v:values){
//v.get() 这个是将intwritable转换为int
sum+=v.get();
}
context.write(key, new IntWritable(sum));
}
}
+

Driver实现

+
public class Driver {
public static void main(String[] args)
throws IOException, ClassNotFoundException, InterruptedException {
System.setProperty("HADOOP_USER_NAME", "hadoop");
//加载配置文件
Configuration conf=new Configuration();
//启动一个job:一个map reduce程序,这里叫做一个job
Job job=Job.getInstance(conf);
//ָ指定job运行的主类
job.setJarByClass(Driver.class);
//指定这个job的mapper类和reduce类
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
//指定map的输出的key和value的类型
//这里为什么还要指定:泛型的只在编译的时候有作用,运行会自动擦除,所以在这里需要指定一下
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//指定reduce输出的key和value类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//指定combiner组件
//job.setCombinerClass(WordCountReducer.class);
//添加自定义分区
//job.setPartitionerClass(MyPartitioner.class);
// 这个参数如果不指定,默认reducetask=1
job.setNumReduceTasks(4);
//传参方式
//FileInputFormat.addInputPath(job, new Path(args[0]));
//添加输出路径:输出路径一定不能存在,怕如果存在会进行覆盖
//FileOutputFormat.setOutputPath(job, new Path(args[1]));
//固定写死
FileInputFormat.addInputPath(job, new Path("hdfs://hadoop01:9000/in"));
FileOutputFormat.setOutputPath(job, new Path("hdfs://hadoop01:9000/out"));
//提交job
job.waitForCompletion(true);
}
}
+

Scala实现

定义数据:array = Array("a b", "c c", "b c")

+

第一种方式实现

val countWord = array.flatMap(_.split(" "))
.map((_,1))
.groupBy(_._1)
.map( x => (x._1, x._2.length))
.toList
.sortBy(_._2)
.reverse
+

中间结果详解

+
    +
  • array.map(_.split(" "))输出:Array(Array("a","b"), Array("c","c"), Array("b","c"))
  • +
  • 使用flatMap(_.split(" "))输出:Array("a","b", "c","c", "b","c")
  • +
  • 再使用map((_,1))输出:Array((a,1), (b,1), (c,1), (c,1), (b,1), (c,1))
  • +
  • 再使用groupBy(_._1)输出:(a,1),(b,1),(b,1),(c,1),(c,1),(c,1),即Map(b -> Array((b,1), (b,1)), a -> Array((a,1)), c -> Array((c,1), (c,1), (c,1)))
  • +
  • 在进行计数:array.flatMap(_.split(" ")).map((_,1)).groupBy(_._1).map( x => (x._1, x._2.length))
  • +
  • 从大到小排序:array.flatMap(_.split(" ")).map((_,1)).groupBy(_._1).map( x => (x._1, x._2.length)).toList.sortBy(_._2).reverse
  • +
+

其他方式实现

val countWord1 = array.map(_.split(" "))
.flatten
.map((_,1))
.groupBy(_._1)
.map(t => (t._1,t._2.size))
.toList
.sortBy(_._2)
.reverse
val countWord2 = array.flatMap(_.split(" "))
.map((_,1))
.groupBy(_._1)
.mapValues(_.size)
.toList
.sortBy(_._2)
.reverse
val countWord3 = array.flatMap(_.split(" "))
.map((_,1))
.groupBy(_._1)
.mapValues(_.foldLeft(0)(_+_._2))
.toList
.sortBy(_._2)
.reverse
+

Spark-shell实现

第一种方式实现

sc.textFile("hdfs://myha/spark/wc/input/words.txt")
.flatMap(_.split(" "))
.map((_, 1))
.reduceByKey(_+_)
.collect
+

详解

+
    +
  • scSparkContext对象,该对象是提交spark程序的入口
  • +
  • textFile("hdfs://myha/spark/wc/input/words.txt")是从HDFS中读取数据
  • +
  • flatMap(_.split(" "))map再压平
  • +
  • map((_,1))将单词和1构成元组
  • +
  • reduceByKey(_+_)按照key进行reduce,并将value累加
  • +
  • saveAsTextFile("hdfs://myha/spark/wc/output")将结果写入到HDFS
  • +
  • 其中:reduceByKey = groupByKey + reduce = groupBy + reduce = groupBy + map
  • +
+

其他方式实现

sc.textFile("hdfs://myha/spark/wc/input/words.txt")
.flatMap(_.split(" "))
.map((_,1))
.reduceByKey(_+_)
.collect
.foreach(println)
sc.textFile("hdfs://myha/spark/wc/input/words.txt")
.flatMap(_.split(" "))
.countByValue
.foreach(println)
sc.textFile("hdfs://myha/spark/wc/input/words.txt")
.flatMap(_.split(" "))
.map((_,1))
.countByKey()
.foreach(println)
+]]>
- - 大数据 - + 大数据 - - - - - 面试 - - 算法 - - - -
- - - - - 算法学习 - - /posts/800507c2/ - -

算法学习

数组和链表

1585056480939

1585056511253

1585056580300

1585056748131

15850568897611585056969448

1585056969448

1585057395924

1585057420437

堆栈和队列

1585057557427

1585057617265

1585057698739

1585058301980

1585058723214

优先队列

1585058974694

1585059046220

1585059134581

15850595851501585061195273

1585061195273

1585061254454

Map和set

1585061567210

1585061666508

1585061724790

1585061856478

1585061932568

1585062074692

1585062360667

1585062384433

1585062402857

1585062640205

1585063037475

1585063051531

1585063206975

]]>
- - + + 算法 + 面试 + +
+ + Java单例模式 + /posts/86ceb8f1/ +

Java单例模式

懒汉式

在初次调用静态方法getSingleton,才会初始化signleton实例。

+

双重检查模式实现

+
public class Singletom {
private volatile static Singletom singletom;
private Singletom(){}
public static Singletom getSingleton(){
if (singletom == null){
synchronized (Singletom.class){
if (singletom == null){
singletom = new Singletom();
}
}
}
return singletom;
}
}
+
    +
  • 实现了延迟初始化,只有在初次调用静态方法getSingleton,才会初始化signleton实例。

    +
  • +
  • 性能优化,同步会造成性能下降,在同步前通过判读singleton是否初始化,减少不必要的同步开销。

    +
  • +
  • 线程安全,同步创建Singleton对象,同时注意到静态变量singleton使用volatile修饰,避免JVM进行优化重排序。

    +
  • +
+ +

静态内部类实现

+
public class Singletom {
private Singletom(){}
public static Singletom getSingleton(){
return Inner.instance;
}
private static class Inner {
private static final Singletom instance = new Singletom();
}
}
+
    +
  • 代码简洁,和双重检查模式对比,静态内部类单例实现清晰明了。
  • +
+
    +
  • 延迟初始化,调用getSingleton才初始化Singleton对象。

    +
  • +
  • 线程安全,JVM在执行类的初始化阶段,会获得一个可以同步多个线程对同一个类的初始化的锁。

    +
  • +
+

饿汉式

直接初始化signleton实例,直接获取实例,没有延迟初始化。

+

多线程安全实现

+
public class Singletom {
private static Singletom instance = new Singletom();
private Singletom(){}
public static Singletom getSingleton(){
return instance;
}
}
+]]>
- - 算法 - + Java - - - - - 面试 - - 算法 - - - -
- - - - - Java单例模式 - - /posts/86ceb8f1/ - -

Java单例模式

懒汉式

在初次调用静态方法getSingleton,才会初始化signleton实例。

双重检查模式实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Singletom {
private volatile static Singletom singletom;
private Singletom(){}
public static Singletom getSingleton(){
if (singletom == null){
synchronized (Singletom.class){
if (singletom == null){
singletom = new Singletom();
}
}
}
return singletom;
}
}
  • 实现了延迟初始化,只有在初次调用静态方法getSingleton,才会初始化signleton实例。

  • 性能优化,同步会造成性能下降,在同步前通过判读singleton是否初始化,减少不必要的同步开销。

  • 线程安全,同步创建Singleton对象,同时注意到静态变量singleton使用volatile修饰,避免JVM进行优化重排序。

静态内部类实现

1
2
3
4
5
6
7
8
9
10
public class Singletom {
private Singletom(){}
public static Singletom getSingleton(){
return Inner.instance;
}
private static class Inner {
private static final Singletom instance = new Singletom();
}
}
  • 代码简洁,和双重检查模式对比,静态内部类单例实现清晰明了。
  • 延迟初始化,调用getSingleton才初始化Singleton对象。

  • 线程安全,JVM在执行类的初始化阶段,会获得一个可以同步多个线程对同一个类的初始化的锁。

饿汉式

直接初始化signleton实例,直接获取实例,没有延迟初始化。

多线程安全实现

1
2
3
4
5
6
7
8
public class Singletom {
private static Singletom instance = new Singletom();
private Singletom(){}
public static Singletom getSingleton(){
return instance;
}
}
]]>
- - + + 面试 + Java + +
+ + ElasticSearch安装避坑 + /posts/62e0a87a/ +

ElasticSearch安装避坑

本文使用Centos7安装ElasticSearch6.5.2,记录避坑指南。

+

升级内核

通过命令查看内核:

+
uname -a
# 3.10.0-327.el7.x86_64
+

Centos7自带的内核为3.10,但是ElasticSearch6.5.2要求系统内核必须在3.5以上,故升级内核,root用户下执行:

+
# 导入key
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
# 安装elrepo的yum源
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm
# 安装内核
yum --enablerepo=elrepo-kernel install kernel-ml-devel kernel-ml
# 查看默认启动顺序
awk -F\' '$1=="menuentry " {print $2}' /etc/grub2.cfg
# 默认启动的顺序是从0开始,新内核是从头插入,选择0
grub2-set-default 0
+

安装完毕后重启reboot生效

+

查看内核为5.5.9:Linux awebone.com 5.5.9-1.el7.elrepo.x86_64 #1 SMP Wed Mar 11 19:01:01 EDT 2020 x86_64 x86_64 x86_64 GNU/Linux

+

如果遇到curl 不兼容或不支持的协议版本的问题,通过以下方法解决:

+
yum update -y nss curl libcurl
+ +

关闭防火墙和SELinux

因为在本地虚拟机安装,关闭防火墙和SELinux,方便测试:

+
# 查看防火墙状态
systemctl status firewalld
# 关闭防火墙
systemctl stop firewalld
# 设置开机不启动
sudo systemctl disable firewalld.service
# 关闭SELinux
setenforce 1
# 查看SELinux状态
getenforce
+

安装JDK1.8和ElasticSearch

通过官网下载安装包elasticsearch-6.5.2.tar.gzjdk-8u73-linux-x64.tar.gz

+

安装JDK

ES要求jdk需要为1.8版本以上,故删除自带的1.7:

+
rpm -qa |grep java
sudo yum -y remove java*
+

解压jdk到apps目录下:

+
tar -zxvf jdk-8u73-linux-x64.tar.gz -C ~/apps/
+

配置环境变量:

+
sudo vim /etc/profile
# 在最后添加以下内容,目录改为自己的:
JAVA_HOME=/home/xxx/apps/jdk1.8.0_73
JRE_HOME=$JAVA_HOME/jre
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
export JAVA_HOME JRE_HOME PATH CLASSPATH
+

最后加载环境变量:source /etc/profile

+

查看JDK版本:java -version

+

es1

+

安装ElasticSearch

注意:ES从2.X版本起,就不能再root用户下安装,故在普通用户下安装

+

解压到apps目录下:

+
tar -zxvf elasticsearch-6.5.2.tar.gz -C ~/apps/
+

配置环境变量:

+
vim ~/.bashrc
# 在最后添加以下内容:
ELASTICSEARCH_HOME=/home/linuxprobe/apps/elasticsearch-6.5.2
export PATH=$PATH:$ELASTICSEARCH_HOME/bin
+

加载环境变量:source ~/.bashrc

+

进行ElasticSearch的配置,修改$ELASTICSEARCH_HOME/conf/elasticsearch.yml文件:

+
vim $ELASTICSEARCH_HOME/conf/elasticsearch.yml
# 填入以下内容,目录改为自己的
cluster.name: es
node.name: hadoop
path.data: /home/xxx/data/elastic(手动创建目录)
path.logs: /home/xxx/logs/elastic(手动创建目录)
network.host: 0.0.0.0
http.port: 9200
+

启动:

+
# es后台启动,不加-d为前台启动
elasticsearch -d
+

测试:

+
# 查看java进程状态
jps
# 查看服务状态
curl -XGET http://localhost:9200
+

es2

+

通过网页查看:

+

es3

+]]>
- - Java - + 大数据 - - - - - 面试 - - Java - - - -
- - - - - ElasticSearch安装避坑 - - /posts/62e0a87a/ - -

ElasticSearch安装避坑

本文使用Centos7安装ElasticSearch6.5.2,记录避坑指南。

升级内核

通过命令查看内核:

1
2
uname -a
# 3.10.0-327.el7.x86_64

Centos7自带的内核为3.10,但是ElasticSearch6.5.2要求系统内核必须在3.5以上,故升级内核,root用户下执行:

1
2
3
4
5
6
7
8
9
10
# 导入key
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
# 安装elrepo的yum源
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm
# 安装内核
yum --enablerepo=elrepo-kernel install kernel-ml-devel kernel-ml
# 查看默认启动顺序
awk -F\' '$1=="menuentry " {print $2}' /etc/grub2.cfg
# 默认启动的顺序是从0开始,新内核是从头插入,选择0
grub2-set-default 0

安装完毕后重启reboot生效

查看内核为5.5.9:Linux awebone.com 5.5.9-1.el7.elrepo.x86_64 #1 SMP Wed Mar 11 19:01:01 EDT 2020 x86_64 x86_64 x86_64 GNU/Linux

如果遇到curl 不兼容或不支持的协议版本的问题,通过以下方法解决:

1
yum update -y nss curl libcurl

关闭防火墙和SELinux

因为在本地虚拟机安装,关闭防火墙和SELinux,方便测试:

1
2
3
4
5
6
7
8
9
10
11
# 查看防火墙状态
systemctl status firewalld
# 关闭防火墙
systemctl stop firewalld
# 设置开机不启动
sudo systemctl disable firewalld.service
# 关闭SELinux
setenforce 1
# 查看SELinux状态
getenforce

安装JDK1.8和ElasticSearch

通过官网下载安装包elasticsearch-6.5.2.tar.gzjdk-8u73-linux-x64.tar.gz

安装JDK

ES要求jdk需要为1.8版本以上,故删除自带的1.7:

1
2
rpm -qa |grep java
sudo yum -y remove java*

解压jdk到apps目录下:

1
tar -zxvf jdk-8u73-linux-x64.tar.gz -C ~/apps/

配置环境变量:

1
2
3
4
5
6
7
8
sudo vim /etc/profile
# 在最后添加以下内容,目录改为自己的:
JAVA_HOME=/home/xxx/apps/jdk1.8.0_73
JRE_HOME=$JAVA_HOME/jre
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
export JAVA_HOME JRE_HOME PATH CLASSPATH

最后加载环境变量:source /etc/profile

查看JDK版本:java -version

es1

安装ElasticSearch

注意:ES从2.X版本起,就不能再root用户下安装,故在普通用户下安装

解压到apps目录下:

1
tar -zxvf elasticsearch-6.5.2.tar.gz -C ~/apps/

配置环境变量:

1
2
3
4
5
vim ~/.bashrc
# 在最后添加以下内容:
ELASTICSEARCH_HOME=/home/linuxprobe/apps/elasticsearch-6.5.2
export PATH=$PATH:$ELASTICSEARCH_HOME/bin

加载环境变量:source ~/.bashrc

进行ElasticSearch的配置,修改$ELASTICSEARCH_HOME/conf/elasticsearch.yml文件:

1
2
3
4
5
6
7
8
9
vim $ELASTICSEARCH_HOME/conf/elasticsearch.yml
# 填入以下内容,目录改为自己的
cluster.name: es
node.name: hadoop
path.data: /home/xxx/data/elastic(手动创建目录)
path.logs: /home/xxx/logs/elastic(手动创建目录)
network.host: 0.0.0.0
http.port: 9200

启动:

1
2
# es后台启动,不加-d为前台启动
elasticsearch -d

测试:

1
2
3
4
5
# 查看java进程状态
jps
# 查看服务状态
curl -XGET http://localhost:9200

es2

通过网页查看:

es3

]]>
- - + + ELK + +
+ + MySQL基本使用 + /posts/75c6e52f/ +

MySQL基本使用

修改MySQL提示符

修改提示符的两种方式:

+
    +
  1. 连接客户端时通过参数指定:shell>mysql -uroot -proot --prompt 提示符
  2. +
  3. 连接上客户端后,通过prompt修改:mysql>prompt 提示符
  4. +
+

修改参数:

+

\D 完整日期
\d 数据库
还可以搭配一起+符号
\h 服务器
\u 用户

+ +

MySQL常用命令

系统查看:

+

VERSION(); 当前数据库版本
NOW();当前系统时间
USER(); 当前登录的用户

+

MySQL语句的规范:

+
    +
  1. 关键字与函数名称全部大写
  2. +
  3. 数据库名称、表名称、字段名称全部小写
  4. +
  5. SQL语句必须以分号结尾
  6. +
+

数据库相关语句

+

成功安装后默认会带4个数据库;{}代表必选项;”|”代表从这里面做选择;中括号[]代表有或没有都可以,可选项。

+
+
    +
  • 查看所有数据库

    +

    SHOW DATABASES;

    +
  • +
  • 查看所有警告

    +

    SHOW WARNINGS;

    +
  • +
  • 查看数据库创建时的信息

    +

    SHOW CREATE DATABASE db_name(数据库名);

    +
  • +
  • 新建数据库

    +

    CREATE {DATABASE|SCHERMA}[IF NOT EXISTS] db_name [DEFAULT] CHARACTER SET = charset_name

    +

    如:新建数据库并设置格式

    +

    CREATE DATABASE IF NOT EXISTS db_name [DEFAULT] (default可省略)CHARACTER SET utf-8(格式,默认utf-8,可以改为任意的);

    +
  • +
  • 修改数据库

    +

    ALTER {DATABASE|SCHEMA}[db_name][DEFAULT] CHARACTER SET charset_name;

    +

    如果需要修改编码格式,可写:

    +

    ALTER DATABASE db_name CHARACTER SET = uft8;

    +
  • +
  • 删除数据库

    +

    DROP {DATABASE|SCHEMA}[IF EXISTS] db_name;

    +
  • +
+

表相关语句

    +
  • 打开某个数据库

    +

    USE db_name;

    +
  • +
  • 查看用户当前所打开的数据库

    +

    SELECT DATABASE();

    +
  • +
  • 创建数据表(如果数据表已存在,加上if not exists,系统将不提示错误,否则会提示错误)

    +

    CREATE TABLE[IF NOT EXISTS] table_name(colume_name data_type);

    +

    列名称:经过分析得到

    +

    数据类型:整型,浮点型等

    +

    注意:逗号是两个字段之间的分隔符,最后一个字段不需要加逗号。

    +

    例子:

    +
    /*打开要创建表的数据库*/
    USE 数据库名;
    /*在打开的数据库中创建表*/
    CREATE TABLE tb1(
    username VARCHAR(20),
    age TINYINT UNSIGNED,
    salary FLOAT(8,2) UNSIGNED
    );
    +
  • +
  • 显示当前数据库的表

    +

    SHOW TABLES;

    +
  • +
  • 显示mysql库中的表

    +

    SHOW TABLES FROM mysql;

    +

    注:但是并没有改变当前数据库,只是显示了一次其他数据库的列表

    +
  • +
  • 查看数据表结构

    +

    SHOW COLUMNS FROM table_name;

    +
  • +
  • 插入数据

    +

    INSERT [INTO] tb_name(表名) [col_name,....](表里的哪几列要赋值,可省略) VALUES(val,...)(值是多少)

    +

    如果省略列的名称,必须给所有字段赋值,否则会报错。

    +
  • +
  • 查询全表

    +

    SELECT * FROM tb1;

    +
  • +
+

创建表时需要注意的字段控制

字段是否为空

+

NULL:字段值可为空

+

NOT NULL:字段值不为空

+

同一个字段不可能既为NULL,又为NOT NULL

+

在创建数据表的时候,如果字段值可为空,可以写NULL,也可省略,不写的话默认为空,如果为空可赋值也可不赋值

+
CREATE TABLE tb2(
username VARCHAR(20) UNSIGNED NOT NULL,
age TINYINT UNSIGNED NULL
);
+

字段是否自增

+

字段为数值型时可为整数或浮点数,为浮点数时小数位必须要为0,如:FLOAT (7,0)

+

AUTO_INCREMENT:自动编号,必须与主键组合使用,否则会报错,默认情况下,起始值为1,每次的增量为1,保证记录唯一性

+

AUTO_INCREMENT必须和PRIMARY KEY 一起使用,每次自增1,可不进行赋值

+

PRIMARY KEY 可以不和AUTO_INCREMENT一起使用,可以被赋值但是不允许有相同值的出现

+
CREATE TABLE tb3(
id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(20) UNSIGNED NOT NULL
);
+

字段是否唯一

+

unique key:唯一约束

+

唯一约束可以保证记录的唯一性

+

唯一约束的字段可以为空值(null),即使存储多个值,最终保留的空值也只有一个,故可以保证唯一性。

+

每张数据表可以存在多个唯一约束,可以存在多个空值null,primary key就只有1个。

+

唯一约束添加语句:username varchar(20) not null unique key

+

达到的效果就是如果插入语句有相同的字段,那么会约束它,只能保证数据唯一性。

+

primary keyunique key的区别

+

primary keyunique key都是唯一性约束,但二者有很大的区别:

+
    +
  1. 作为primary key的1个或多个列必须为NOT NULL,而unique key约束的列可以为null,这是primary keyunique key最大的区别。
  2. +
  3. 一个表只能有一个primary key(单列或多列,多列主键叫联合主键),但可以有多个unique key
  4. +
+

默认值设置

+

default 设置:当插入记录时,如果没有明确为字段赋值,则自动赋予默认值

+

sex enum('1','2','3') default '3'

+

这个语句要达成的效果就是性别提供三个选项:1男,2女,3保密,那么如果数据插入没有添加性别,那么默认为3选项

+

数据类型

字符型

+

mysql_char

+

整型

+

mysql_int

+

浮点型

+

mysql_float

+

日期时间型

+

mysql_data

+

数据表操作:插入几录 查找记录
记录操作:创建数据表 约束的使用

+

create table table_name 创建数据表
show columns from table_name查看数据表结构
select*from table_name数据查找,验证数据是否成功写入。

+

auto_increment必须要和主键一起使用 但是主键可以不和auto_increment一起使用 不一起使用时主键可以自主赋值
PRIMARY KEY 主键约束 一张表只能有一个主键约束
Unique key 唯一约束 一个表可以有多个Unique约束
default 默认约束

+

具有外键列的表称为子表;子表所参照的表称为父表
1.父表和子表必须使用相同的存储引擎,而且禁止使用临时表
2.数据表的存储引擎只能为InnoDB
3.外键列和参照列必须具有相似的数据类型,其中数字的长度或是否有符号位必须相同;而字符的长度则可以不同
4.外键列和参照列必须创建索引,如果参照列不存在索引的话,mysql将自动创建索引;如果外键列没有索引,mysql将不会自动创建索引(此处根据语音修改,与PPT内容不一致——经查,mysql5.5以上的版本不会自动创建外键索引,但根据实际情况,创建外建索引很有必要。)

+

表级约束:约束只针对某一字段
列级约束:约束针对两个及两个以上字段
FOREIGN KEY(外键约束):保持数据的一致性,完整性。实现数据表的一对一,一对多的关系。
1,父表(子表所参照的表)和子表(具有外键列的表)必须使用相同的存储引擎,而且禁止使用临时表。
2,数据表的存储引擎只能为InnoDB(可在my.ini查看修改。5.7版本my.ini地址:C:\ProgramData\MySQL\MySQL Server 5.7\my.ini)。
3,外键列(曾经加过foreign关键词的那一列)和参照列(外键列所参照的那列)必须具有相似的数据类型(字符,整型,日期时间等)。其中数字的长度或是否有符号位(如整型有无符号(unsigned)和有符号(signed)两种类型;)必须相同;而字符的长度则可以不同。比如说父表里面有一个参数id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,子表里面就要写作pid SMALLINT UNSIGNED(符号位和数据类型要相似)
4,外键列和参照列必须创建索引。如果外键列不存在索引的话,MySQL将自动创建索引。
FOREIGN KEY (pid)REFERENCES 父表名(id)
也就是users表中有两个索引(id pid)
外键列:pid (可自定义)
参照列:id (可自定义)
SHOW INDEXES FROM table_name查看索引
SHOW INDEXES FROM table_name\G;以网格方式来查看索引

+

外键约束的参照操作:
在实际的项目开发中,为避免受引擎限制,通常使用逻辑外键约束,而不使用此物理的外键约束(按照外键的定义来设计数据表,但不使用FOREIGN KEY)。
1.CASCADE从父表删除或更新时自动删除或更新子表中的匹配行
2.SET NULL从父表删除或更新行时,设置子表中的外键列为NULL。如果使用该选项,必须保证子表列没有指定NOT NULL
3.RESTRICT拒绝对父表的删除或更新操作
4.NO ACTION标准的SQL关键字,在mysql中与RESTRICT作用相同

+

对于一个列所创建的约束,称之为列级约束。
而对于两个或两个以上的列所创建的约束,我们称之为表级约束。
列级约束在使用时,既可以在列定义的时候声明,也可以在列定义以后声明,而表级的约束只能在列定义以后来声明。
在实际开发中,用列级约束比较多,表级约束很少用,
在所有的约束中,并不是说每种约束都存在着表级或列级约束,其中,NOT NULL 非空约束,DEFAULT约束这两种约束就不存在表级约束,它们只有列级约束,而对于其他的三种,像主键,唯一,外键,它们都可以存在表级和列级约束。

+

删除列:ALTER TABLE tb1_name DROP[COLUMN] col_name;
添加多列:ALTER TABLE tb1_name ADD[COLUMN] (col_name column_definition,…);
添加单列:ALTER TABLE tb1_name ADD[COLUMN] col_name column_definition [FIRST|AFTER col_name];
删除记录:DELETE FROM province WHERE id=3;
验证表中是否有相应的记录:SELECT * FROM province;
显示索引:SHOW INDEXES FROM province;SHOW INDEXES FROM province\G;(以网格呈现)
打开数据表test:USE test;
查看创建命令:SHOW CREATE TABLE province;
查看数据表结构:SHOW COLUMNS FROM tb3;
插入记录:INSERT [INTO] tb1_name [(col_name,…)] VALUES (val,…);
查看数据表列表:SHOW TABLES [FROM db_name] [LIKE ‘pattern’|WHERE expr];
添加的单列将他至于那一列后面语句:after 后面跟要添加其下的列名
alter table users1 add 要添加的列名 varchar(32) not null after 列名;
将添加的单列位于所有列之前:first
alter table users1 add 要添加的列名和属性 first;
多个操作可以同时操作,用逗号分开

+

增加一行
ALTER TABLE tb_name ADD age SMALLINT UNSIGNED NOT NULL;
添加主键约束(只能添加一个)
ALTER TABLE tbl_name ADD [CONSTRAINT [symbol自定义的约束的名称]] PRIMARY KEY [index_type] (index_col_name,…)
ALTER TABLE tb_1 ADD PRIMARY KEY(id);
添加唯一约束(可以添加多个)
ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] UNIQUE [index_type] (index_col_name,…)
ALTER TABLE tb_1 ADD UNIQUE (username);
添加外键约束
ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_type] (index_col_name,…)
reference_definition
例:ALTER TABLE t3 ADD FOREIGN KEY (age)REFERENCES t2(age);
添加/删除默认约束
ALTER TABLE tbl_name ALTER [COLUMN] col_name SET DAFAULT literal(比如age里面可设置为10,20 |DROP DEFAULT
例:ALTER TABLE user2 ALTER age SET DEFAULT 15;
ALTER TABLE user2 ALTER age DROP DEFAULT;

+

查索引是SHOW INDEX
查约束是SHOW INDEXES
约束和索引, 前者是用来检查数据的正确性,后者用来实现数据查询的优化,目的不同。
唯一性约束与唯一索引有所不同:
(1).创建唯一约束会在Oracle中创建一个Constraint,同时也会创建一个该约束对应的唯一索引。
(2).创建唯一索引只会创建一个唯一索引,不会创建Constraint。
也就是说其实唯一约束是通过创建唯一索引来实现的。
在删除时这两者也有一定的区别:
删除唯一约束时可以只删除约束而不删除对应的索引,所以对应的列还是必须唯一的,
而删除了唯一索引的话就可以插入不唯一的值。
删除唯一约束:ALTER TABLE table_name DROP INDEX 数据名;
PRIMARY KEY 和 KEY 的区别:
主键一定是唯一性索引,唯一性索引并不一定就是主键
一个表中可以有多个唯一性索引,但只能有一个主键
主键列不允许空值,而唯一性索引列允许空值
删除主键约束:alter table user2 drop primary key;
不用选择字段 因为一张表有也只有一个主键。
删除外键约束:alter table 数据表名 drop foreign key user_ibfk_1;
在删除之前要先找到外键名 需用show create table 数据表名;来查看

+

1.修改列定义
用关键字ALTER TABLE..MODIFY
ALTER TABLE tbl_name MODIFY [COLUMN] col_name column_definition [FIRST |AFTER col_name];
ALTER TABLE users2 MODIFY id SMALLINT UNSIGNED NOT NULL FIRST; //将id字段的位置提到第一列
SHOW COLUMNS FROM users2;
ALTER TABLE users2 MODIFY id TINYINT UNSIGNED NOT NULL; //修改数据类型,需注意数据丢失的问题

+

2.修改列名称,用CHANGE方法可以同时修改列名称和列定义.
用关键字ALTER..CHANGE
ALTER TABLE tbl_name CHANGE [COLUMN] col_name new_col_name column_definition [FIRST|AFTER col_name];
ALTER TABLE users2 CHANGE pid p_id TINYINT UNSIGNED; //修改列名称

+

3.更换数据表名
用关键字ALTER..RENAME
修改一个表的表名(方法1)
ALTER TABLE users2 RENAME person;
修改一个表的表名(方法2)
用关键字RENAME..TO
RENAME TABLE users5 TO users2;
一次修改多个表的表名,操作间用逗号隔开.
RENAME TABLE users5 TO users2,users3 TO users4;
应该少使用数据表的列名及表名的更名。

+
    +
  1. 创建表:
    create table user(
    id smallint primary key not null auto_increment,
    +name varchar(20),
    +age smallint
    +
    );
  2. +
  3. show create table user; 查看创建表信息
    show tables; 显示当前数据库所有的表
    show columns from user; 显示列属性 或 discribe user;
    show indexes from user \G; 显示所有的索引,“\G” 表示按列显示
  4. +
  5. drop table user1; 删除表
  6. +
  7. 表添加一列: alter table user add age tinyint
    表删除一列: alter table user drop age;
  8. +
  9. 添加主键约束:alter table user2 add primary key (id);
    删除主键约束:alter table user2 drop primary key;
    添加唯一约束: alter table user2 add unique key uni_key (name);
    删除唯一约束: drop index uni_key on user2;
    添加外键约束:alter table user2 add foreign key (age) references user(id);
    添加默认约束:alter table user2 alter age set default 20;
    删除默认约束:alter table user2 alter age drop default;
    修改列属性:alter table user2 modify name varchar(30);
    修改列名:alter table user2 change age age1 tinyint not null;
    修改表名:alter tabler user2 rename user3 或者 rename table user3 to user2;
    注:尽量不要修改列名和表名
  10. +
+]]>
- - 大数据 - + 数据库 - - - - - ELK - - - -
- - - - - MySQL基本使用 - - /posts/75c6e52f/ - -

MySQL基本使用

修改mysql提示符

修改提示符的两种方式:

  1. 连接客户端时通过参数指定:shell>mysql -uroot -proot –prompt 提示符
  2. 连接上客户端后,通过prompt修改:mysql>prompt 提示符

修改参数:

\D 完整日期
\d 数据库
还可以搭配一起+符号
\h 服务器
\u 用户

mysql常用命令

系统查看:

VERSION(); 当前数据库版本
NOW();当前系统时间
USER(); 当前登录的用户

mysql语句的规范:

  1. 关键字与函数名称全部大写
  2. 数据库名称、表名称、字段名称全部小写
  3. SQL语句必须以分号结尾

数据库相关语句

成功安装后默认会带4个数据库;{}代表必选项;”|”代表从这里面做选择;中括号[]代表有或没有都可以,可选项。

  • 查看所有数据库

    SHOW DATABASES;

  • 查看所有警告

    SHOW WARNINGS;

  • 查看数据库创建时的信息

    SHOW CREATE DATABASE db_name(数据库名);

  • 新建数据库

    CREATE {DATABASE|SCHERMA}[IF NOT EXISTS] db_name [DEFAULT] CHARACTER SET = charset_name

    如:新建数据库并设置格式

    CREATE DATABASE IF NOT EXISTS db_name [DEFAULT] (default可省略)CHARACTER SET utf-8(格式,默认utf-8,可以改为任意的);

  • 修改数据库

    ALTER {DATABASE|SCHEMA}[db_name][DEFAULT] CHARACTER SET charset_name;

    如果需要修改编码格式,可写:

    ALTER DATABASE db_name CHARACTER SET = uft8;

  • 删除数据库

    DROP {DATABASE|SCHEMA}[IF EXISTS] db_name;

表相关语句

  • 打开某个数据库

    USE db_name;

  • 查看用户当前所打开的数据库

    SELECT DATABASE();

  • 创建数据表(如果数据表已存在,加上if not exists,系统将不提示错误,否则会提示错误)

    CREATE TABLE[IF NOT EXISTS] table_name(colume_name data_type);

    列名称:经过分析得到

    数据类型:整型,浮点型等

    注意:逗号是两个字段之间的分隔符,最后一个字段不需要加逗号。

    例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    /*打开要创建表的数据库*/
    USE 数据库名;
    /*在打开的数据库中创建表*/
    CREATE TABLE tb1(
    username VARCHAR(20),
    age TINYINT UNSIGNED,
    salary FLOAT(8,2) UNSIGNED
    );
  • 显示当前数据库的表

    SHOW TABLES;

  • 显示mysql库中的表

    SHOW TABLES FROM mysql;

    注:但是并没有改变当前数据库,只是显示了一次其他数据库的列表

  • 查看数据表结构

    SHOW COLUMNS FROM table_name;

  • 插入数据

    INSERT [INTO] tb_name(表名) [col_name,....](表里的哪几列要赋值,可省略) VALUES(val,...)(值是多少)

    如果省略列的名称,必须给所有字段赋值,否则会报错。

  • 查询全表

    SELECT * FROM tb1;

创建表时需要注意的字段控制

字段是否为空

NULL:字段值可为空

NOT NULL:字段值不为空

同一个字段不可能既为NULL,又为NOT NULL

在创建数据表的时候,如果字段值可为空,可以写NULL,也可省略,不写的话默认为空,如果为空可赋值也可不赋值

1
2
3
4
CREATE TABLE tb2(
username VARCHAR(20) UNSIGNED NOT NULL,
age TINYINT UNSIGNED NULL
);

字段是否自增

字段为数值型时可为整数或浮点数,为浮点数时小数位必须要为0,如:FLOAT (7,0)

AUTO_INCREMENT:自动编号,必须与主键组合使用,否则会报错,默认情况下,起始值为1,每次的增量为1,保证记录唯一性

AUTO_INCREMENT必须和PRIMARY KEY 一起使用,每次自增1,可不进行赋值

PRIMARY KEY 可以不和AUTO_INCREMENT一起使用,可以被赋值但是不允许有相同值的出现

1
2
3
4
CREATE TABLE tb3(
id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(20) UNSIGNED NOT NULL
);

字段是否唯一

unique key:唯一约束

唯一约束可以保证记录的唯一性

唯一约束的字段可以为空值(null),即使存储多个值,最终保留的空值也只有一个,故可以保证唯一性。

每张数据表可以存在多个唯一约束,可以存在多个空值null,primary key就只有1个。

唯一约束添加语句:username varchar(20) not null unique key

达到的效果就是如果插入语句有相同的字段,那么会约束它,只能保证数据唯一性。

primary keyunique key的区别

primary keyunique key都是唯一性约束,但二者有很大的区别:

  1. 作为primary key的1个或多个列必须为NOT NULL,而unique key约束的列可以为null,这是primary keyunique key最大的区别。
  2. 一个表只能有一个primary key(单列或多列,多列主键叫联合主键),但可以有多个unique key

默认值设置

default 设置:当插入记录时,如果没有明确为字段赋值,则自动赋予默认值

sex enum('1','2','3') default '3'

这个语句要达成的效果就是性别提供三个选项:1男,2女,3保密,那么如果数据插入没有添加性别,那么默认为3选项

数据类型

字符型

mysql_char

整型

mysql_int

浮点型

mysql_float

日期时间型

mysql_data

数据表操作:插入几录 查找记录
记录操作:创建数据表 约束的使用

create table table_name 创建数据表
show columns from table_name查看数据表结构
select*from table_name数据查找,验证数据是否成功写入。

auto_increment必须要和主键一起使用 但是主键可以不和auto_increment一起使用 不一起使用时主键可以自主赋值
PRIMARY KEY 主键约束 一张表只能有一个主键约束
Unique key 唯一约束 一个表可以有多个Unique约束
default 默认约束

具有外键列的表称为子表;子表所参照的表称为父表
1.父表和子表必须使用相同的存储引擎,而且禁止使用临时表
2.数据表的存储引擎只能为InnoDB
3.外键列和参照列必须具有相似的数据类型,其中数字的长度或是否有符号位必须相同;而字符的长度则可以不同
4.外键列和参照列必须创建索引,如果参照列不存在索引的话,mysql将自动创建索引;如果外键列没有索引,mysql将不会自动创建索引(此处根据语音修改,与PPT内容不一致——经查,mysql5.5以上的版本不会自动创建外键索引,但根据实际情况,创建外建索引很有必要。)

表级约束:约束只针对某一字段
列级约束:约束针对两个及两个以上字段
FOREIGN KEY(外键约束):保持数据的一致性,完整性。实现数据表的一对一,一对多的关系。
1,父表(子表所参照的表)和子表(具有外键列的表)必须使用相同的存储引擎,而且禁止使用临时表。
2,数据表的存储引擎只能为InnoDB(可在my.ini查看修改。5.7版本my.ini地址:C:\ProgramData\MySQL\MySQL Server 5.7\my.ini)。
3,外键列(曾经加过foreign关键词的那一列)和参照列(外键列所参照的那列)必须具有相似的数据类型(字符,整型,日期时间等)。其中数字的长度或是否有符号位(如整型有无符号(unsigned)和有符号(signed)两种类型;)必须相同;而字符的长度则可以不同。比如说父表里面有一个参数id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,子表里面就要写作pid SMALLINT UNSIGNED(符号位和数据类型要相似)
4,外键列和参照列必须创建索引。如果外键列不存在索引的话,MySQL将自动创建索引。
FOREIGN KEY (pid)REFERENCES 父表名(id)
也就是users表中有两个索引(id pid)
外键列:pid (可自定义)
参照列:id (可自定义)
SHOW INDEXES FROM table_name查看索引
SHOW INDEXES FROM table_name\G;以网格方式来查看索引

外键约束的参照操作:
在实际的项目开发中,为避免受引擎限制,通常使用逻辑外键约束,而不使用此物理的外键约束(按照外键的定义来设计数据表,但不使用FOREIGN KEY)。
1.CASCADE从父表删除或更新时自动删除或更新子表中的匹配行
2.SET NULL从父表删除或更新行时,设置子表中的外键列为NULL。如果使用该选项,必须保证子表列没有指定NOT NULL
3.RESTRICT拒绝对父表的删除或更新操作
4.NO ACTION标准的SQL关键字,在mysql中与RESTRICT作用相同

对于一个列所创建的约束,称之为列级约束。
而对于两个或两个以上的列所创建的约束,我们称之为表级约束。
列级约束在使用时,既可以在列定义的时候声明,也可以在列定义以后声明,而表级的约束只能在列定义以后来声明。
在实际开发中,用列级约束比较多,表级约束很少用,
在所有的约束中,并不是说每种约束都存在着表级或列级约束,其中,NOT NULL 非空约束,DEFAULT约束这两种约束就不存在表级约束,它们只有列级约束,而对于其他的三种,像主键,唯一,外键,它们都可以存在表级和列级约束。

删除列:ALTER TABLE tb1_name DROP[COLUMN] col_name;
添加多列:ALTER TABLE tb1_name ADD[COLUMN] (col_name column_definition,…);
添加单列:ALTER TABLE tb1_name ADD[COLUMN] col_name column_definition [FIRST|AFTER col_name];
删除记录:DELETE FROM province WHERE id=3;
验证表中是否有相应的记录:SELECT * FROM province;
显示索引:SHOW INDEXES FROM province;SHOW INDEXES FROM province\G;(以网格呈现)
打开数据表test:USE test;
查看创建命令:SHOW CREATE TABLE province;
查看数据表结构:SHOW COLUMNS FROM tb3;
插入记录:INSERT [INTO] tb1_name [(col_name,…)] VALUES (val,…);
查看数据表列表:SHOW TABLES [FROM db_name] [LIKE ‘pattern’|WHERE expr];
添加的单列将他至于那一列后面语句:after 后面跟要添加其下的列名
alter table users1 add 要添加的列名 varchar(32) not null after 列名;
将添加的单列位于所有列之前:first
alter table users1 add 要添加的列名和属性 first;
多个操作可以同时操作,用逗号分开

增加一行
ALTER TABLE tb_name ADD age SMALLINT UNSIGNED NOT NULL;
添加主键约束(只能添加一个)
ALTER TABLE tbl_name ADD [CONSTRAINT [symbol自定义的约束的名称]] PRIMARY KEY [index_type] (index_col_name,…)
ALTER TABLE tb_1 ADD PRIMARY KEY(id);
添加唯一约束(可以添加多个)
ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] UNIQUE [index_type] (index_col_name,…)
ALTER TABLE tb_1 ADD UNIQUE (username);
添加外键约束
ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_type] (index_col_name,…)
reference_definition
例:ALTER TABLE t3 ADD FOREIGN KEY (age)REFERENCES t2(age);
添加/删除默认约束
ALTER TABLE tbl_name ALTER [COLUMN] col_name SET DAFAULT literal(比如age里面可设置为10,20 |DROP DEFAULT
例:ALTER TABLE user2 ALTER age SET DEFAULT 15;
ALTER TABLE user2 ALTER age DROP DEFAULT;

查索引是SHOW INDEX
查约束是SHOW INDEXES
约束和索引, 前者是用来检查数据的正确性,后者用来实现数据查询的优化,目的不同。
唯一性约束与唯一索引有所不同:
(1).创建唯一约束会在Oracle中创建一个Constraint,同时也会创建一个该约束对应的唯一索引。
(2).创建唯一索引只会创建一个唯一索引,不会创建Constraint。
也就是说其实唯一约束是通过创建唯一索引来实现的。
在删除时这两者也有一定的区别:
删除唯一约束时可以只删除约束而不删除对应的索引,所以对应的列还是必须唯一的,
而删除了唯一索引的话就可以插入不唯一的值。
删除唯一约束:ALTER TABLE table_name DROP INDEX 数据名;
PRIMARY KEY 和 KEY 的区别:
主键一定是唯一性索引,唯一性索引并不一定就是主键
一个表中可以有多个唯一性索引,但只能有一个主键
主键列不允许空值,而唯一性索引列允许空值
删除主键约束:alter table user2 drop primary key;
不用选择字段 因为一张表有也只有一个主键。
删除外键约束:alter table 数据表名 drop foreign key user_ibfk_1;
在删除之前要先找到外键名 需用show create table 数据表名;来查看

1.修改列定义
用关键字ALTER TABLE..MODIFY
ALTER TABLE tbl_name MODIFY [COLUMN] col_name column_definition [FIRST |AFTER col_name];
ALTER TABLE users2 MODIFY id SMALLINT UNSIGNED NOT NULL FIRST; //将id字段的位置提到第一列
SHOW COLUMNS FROM users2;
ALTER TABLE users2 MODIFY id TINYINT UNSIGNED NOT NULL; //修改数据类型,需注意数据丢失的问题

2.修改列名称,用CHANGE方法可以同时修改列名称和列定义.
用关键字ALTER..CHANGE
ALTER TABLE tbl_name CHANGE [COLUMN] col_name new_col_name column_definition [FIRST|AFTER col_name];
ALTER TABLE users2 CHANGE pid p_id TINYINT UNSIGNED; //修改列名称

3.更换数据表名
用关键字ALTER..RENAME
修改一个表的表名(方法1)
ALTER TABLE users2 RENAME person;
修改一个表的表名(方法2)
用关键字RENAME..TO
RENAME TABLE users5 TO users2;
一次修改多个表的表名,操作间用逗号隔开.
RENAME TABLE users5 TO users2,users3 TO users4;
应该少使用数据表的列名及表名的更名。

  1. 创建表:
    create table user(
    id smallint primary key not null auto_increment,name varchar(20),age smallint
    );
  2. show create table user; 查看创建表信息
    show tables; 显示当前数据库所有的表
    show columns from user; 显示列属性 或 discribe user;
    show indexes from user \G; 显示所有的索引,“\G” 表示按列显示
  3. drop table user1; 删除表
  4. 表添加一列: alter table user add age tinyint
    表删除一列: alter table user drop age;
  5. 添加主键约束:alter table user2 add primary key (id);
    删除主键约束:alter table user2 drop primary key;
    添加唯一约束: alter table user2 add unique key uni_key (name);
    删除唯一约束: drop index uni_key on user2;
    添加外键约束:alter table user2 add foreign key (age) references user(id);
    添加默认约束:alter table user2 alter age set default 20;
    删除默认约束:alter table user2 alter age drop default;
    修改列属性:alter table user2 modify name varchar(30);
    修改列名:alter table user2 change age age1 tinyint not null;
    修改表名:alter tabler user2 rename user3 或者 rename table user3 to user2;
    注:尽量不要修改列名和表名
]]>
- - + + MySQL + +
+ + 使用JavaScript实现焦点轮播图 + /posts/7a7093e6/ +

使用JavaScript实现焦点轮播图

原理

各大网站都使用焦点轮播图来展示自己的图片,如淘宝、京东等。

+
    +
  1. 焦点轮播图所用技能点:DOM操作、定时器、事件运用、JS动画、函数递归、无限滚动;
  2. +
  3. 无限滚动实现:包含图片的父级标签要有一个属性overflow:hidden 来隐藏超出自身尺寸的内容;有style:left通过控制left值来实现滚动; 图片列表中要在开始和结束位置添加两张相同的附属图,使图片实现无缝连接。
  4. +
+ +

使用html和css实现静态页面布局

    +
  1. 父容器要承载图片、圆点下标、左右切换箭头,要让超出部分隐藏overflow:hidden、定位为position:relative
  2. +
  3. 图片的div要添加定位:position:absolute让它基于父容器relative,z-index:1使图片堆叠在第一层上;
  4. +
  5. 圆点下标和左右切换箭头设置z-index:2position:absolute,让其覆盖在图片上;
  6. +
  7. 左右切换箭头在初始状态下设置为隐藏display:none,鼠标移上图片时使其显示display:block,鼠标移到箭头上时改变透明度RGBA,使箭头颜色加深;
  8. +
+

HTML代码

+
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>焦点轮播图</title>
<link rel="stylesheet" type="text/css" href="css/焦点轮播图.css">
</head>
<body>
<div id="container">
<div id="list" style="left: -600px">
<img src="images/5.jpg" alt="5"> <!-- 附属图实现无缝的滚动 -->
<img src="images/1.jpg" alt="1">
<img src="images/2.jpg" alt="2">
<img src="images/3.jpg" alt="3">
<img src="images/4.jpg" alt="4">
<img src="images/5.jpg" alt="5">
<img src="images/1.jpg" alt="5">
</div>
<div id="buttons">
<span index="1" class="on"></span>
<span index="2"></span>
<span index="3"></span>
<span index="4"></span>
<span index="5"></span>
</div>
<a href="javascript:;" id="prev" class="arrow">&lt;</a>
<a href="javascript:;" id="next" class="arrow">&gt;</a>
</div>
<script type="text/javascript" src="js/焦点轮播图.js"></script>
</body>
</html>
+

CSS代码

+
*{
margin: 0;
padding: 0;
text-decoration :none;
}
body{
padding: 20px;
}
#container{
width: 600px;
height: 400px;
position: relative;
border: 3px solid #333;
overflow: hidden;
}
#list{
height: 400px;
width: 4200px;
position: absolute;
z-index: 1; /*设置元素的堆叠顺序*/
}
#list img{
float: left;
}
#buttons{
height: 10px;
width: 100px;
z-index: 2;
bottom: 20px;
left: 250px;
position: absolute;
}
#buttons span {
cursor: pointer; /*规定要显示的光标的类型(手指)*/
float: left;
border: 1px solid #fff;
width: 10px;
height: 10px;
border-radius: 50%;
background: #333;
margin-right: 5px;
}
#buttons .on {
background: orangered;
}
.arrow {
cursor: pointer;
display: none; /*箭头隐藏*/
line-height: 39px;
text-align: center;
font-size: 36px;
font-weight: bold;
width: 40px; height: 40px;
position: absolute;
z-index: 2;
top: 180px;
background-color: RGBA(0,0,0,.3); /*透明度设置*/
color: #fff;
}
.arrow:hover {
background-color: RGBA(0,0,0,.7);
}
#container:hover .arrow {
display: block; /*箭头显示*/
}
#prev {
left: 20px;
}
#next {
right: 20px;
}
+

JS动画实现

箭头切换 -> 无限滚动 -> 按钮切换 -> 延迟切换 -> 自动播放

+
    +
  1. 箭头切换

    +
      +
    • 整个页面加载window.onload,获取元素
    • +
    • 通过ID名获取页面中的元素(父容器、承载图片容器、圆点列表、箭头),赋值给一个变量
    • +
    • 添加一个时间绑定,点击箭头时实现图片的切换
    • +
    • 当点击右箭头时,改变left的值,向左移动,要减去一张图的宽度
    • +
    • 获取图片容器的值,list.style.left = 自身的值再减去一张图片的宽度
      注意要把等号后面字符串使用parseInt函数转换为数字才可以进行减法,减去的图片宽度要加px单位
    • +
    • 反方向同理,加上一张图片的宽度
    • +
    • 左右箭头的写法很相似,只是加减不一样,可以封装成一个函数,通过参数的正负值实现加减
    • +
    +
  2. +
+
    +
  1. 无限滚动:弥补左右键切换的空白

    +
      +
    • 当前面的附属图比第一张大,最后一张附属图比最后一张小的时候,出现这两种情况时让它复位到真正的第一张或第五张图
    • +
    • 判断是否滚到了辅助图上,滚到了让它归位
    • +
    • 把常用的list.style.left,存到一个变量中,方便使用
    • +
    • 添加圆点的切换功能,创建一个变量来承载当前存储的第几张图片/显示第个圆点
    • +
    • 写一个函数,用来显示亮起小圆点的功能
        +
      • 圆点是数组,所以创建的变量要减去1才能对应上要显示的圆点,让它亮起来添加class名
        <span index="1" class="on">
      • +
      +
    • +
    • 再绑定事件中左箭头index要加一,右箭头要减一,调用圆点函数让它点击时显示,每次点击箭头的时候都要改变index的值,使它对应到正确的图片上,调用showButton亮起对应的圆点
    • +
    • 亮起自己的同时,让其他不亮,使用for循环,去掉所有的class,然后break退出循环,不再继续遍历元素节点
    • +
    • 箭头点击时,当圆点index大于5时,让它归位为1,小于1时,归位为5,不到5时加1
    • +
    +
  2. +
+
    +
  1. 圆点按钮切换

    +
      +
    • 通过for循环遍历圆点,添加点击事件

      +
    • +
    • 点击按钮时,取到index值,就可以知道当前点击的是第几个按钮,要显示第几张图片

      +
    • +
    • 通过DOM2级方法getAttribute()获取到自定义(或自带)属性,为了计算再转换为数字var myIndex = parseInt(this.getAttribute('index'));

      +
    • +
    • 通过新的值减去旧的值获取偏移量var offset = -600 * (myIndex - index);

      +
    • +
    • 写一个判断,当这张图片是打开状态的,就什么都不做,用class=on来判断是否打开,return跳出,后面的代码不会再执行

      +
      if (animated) {
      return;
      }
      if (this.className == 'on') {
      return;
      }
      +
    • +
    +
  2. +
+
    +
  1. 动画函数

    +
      +
    • 图片在一定时间内进行位移,要判断是否达到目标值,没有达到还要继续做位移
    • +
    • 声明一个变量用offset总共的偏移量除以次数(位移总时间time除以位移间隔时间inteval),求出每次移动多少var speed = offset / (time / inteval);
    • +
    • 判断speed小于0并且left值是否大于目标值newLeft或speed大于0并且left值小于目标值,这两种情况让它做位移speed > 0 && parseInt(list.style.left) < left) || (speed < 0 && parseInt(list.style.left) > left
    • +
    • 在判断中放入定时器setTimeout
      一个函数不停的在一定的条件之后调用自身这种做法叫做递归
    • +
    +
  2. +
+
    +
  • 优化:声明一个变量,作为动画是否在运行的依据,开始状态为false表示没有运行var animated = false; //优化
  • +
+
    +
  1. 自动播放

    +
      +
    • 鼠标移开时自动播放,鼠标移上去时停止,通过定时器setTimeoutclearTimeout来实现的
    • +
    • 设置定时器,让它隔几秒切换一次,相当于3秒钟调一次next.onclick(右箭头)事件
    • +
    • 自动切换需要写两个函数来控制自动切换,声明一个变量来存放定时器不给任何值
    • +
    • 鼠标移开时定时器执行,移上时清除定时器执行,要给整个容器加一个鼠标移入移开事件
    • +
    • 鼠标不做任何事情时让它自动播放,调用函数
    • +
    +
  2. +
+

代码如下

+
window.onload = function() {
var container = document.getElementById('container');
var list = document.getElementById('list');
var buttons = document.getElementById('buttons').getElementsByTagName('span');
var prev = document.getElementById('prev');
var next = document.getElementById('next');
var index = 1; //索引
var len = 5;
var animated = false; //优化
var interval = 3000; //时间间隔
var timer;
function showButton() {
for (var i = 0; i < buttons.length; i++) {
if (buttons[i].className == 'on') {
buttons[i].className = '';
break;
}
}
buttons[index - 1].className = 'on';
} //按钮切换
next.onclick = function() {
if (animated) {
return;
}
if (index == 5) {
index = 1;
} else {
index += 1;
}
animate(-600);
showButton();
}//右切换
prev.onclick = function() {
if (animated) {
return;
}
if (index == 1) {
index = 5;
} else {
index -= 1;
}
animate(600);
showButton();
}//左切换
function play() {
timer = setTimeout(function() {
next.onclick();
play();
}, interval);
}
function stop() {
clearTimeout(timer);
}
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function() {
if (animated) {
return;
}
if (this.className == 'on') {
return;
}
var myIndex = parseInt(this.getAttribute('index'));
var offset = -600 * (myIndex - index);
animate(offset);
index = myIndex;
showButton();
}
}
function animate(offset) {
if (offset == 0) {
return;
}
animated = true;
var time = 300; //时间
var inteval = 10; //时间间隔
var speed = offset / (time / inteval); //速度
var left = parseInt(list.style.left) + offset; //改变值来实现滚动
var go = function() {
if ((speed > 0 && parseInt(list.style.left) < left) || (speed < 0 && parseInt(list.style.left) > left)) {
list.style.left = parseInt(list.style.left) + speed + 'px';
setTimeout(go, inteval);
} else {
list.style.left = left + 'px';
if (left > -200) {
list.style.left = -600 * len + 'px';
}
if (left < (-600 * len)) {
list.style.left = '-600px';
}
animated = false;
}
} //自动滚动
go();
}
container.onmouseover = stop();
container.onmouseout = play();
play();
}
+

总结

焦点轮播图的实现需要耐心分析原理,掌握焦点轮播图所需的技能点,从而通过代码实现。

+

先写出静态页面html+css,注意属性值的设置。再用js一步一步写出箭头切换、按钮切换的函数,学会设置和清除定时器、递归调用函数,实现自动滚动播放。

+]]>
- - 数据库 - + web前端 - - - - - MySQL - - - -
- - - - - 使用JavaScript实现焦点轮播图 - - /posts/7a7093e6/ - -

使用JavaScript实现焦点轮播图

原理

各大网站都使用焦点轮播图来展示自己的图片,如淘宝、京东等。

  1. 焦点轮播图所用技能点:DOM操作、定时器、事件运用、JS动画、函数递归、无限滚动;
  2. 无限滚动实现:包含图片的父级标签要有一个属性overflow:hidden 来隐藏超出自身尺寸的内容;有style:left通过控制left值来实现滚动; 图片列表中要在开始和结束位置添加两张相同的附属图,使图片实现无缝连接。

使用html和css实现静态页面布局

  1. 父容器要承载图片、圆点下标、左右切换箭头,要让超出部分隐藏overflow:hidden、定位为position:relative
  2. 图片的div要添加定位:position:absolute让它基于父容器relative,z-index:1使图片堆叠在第一层上;
  3. 圆点下标和左右切换箭头设置z-index:2position:absolute,让其覆盖在图片上;
  4. 左右切换箭头在初始状态下设置为隐藏display:none,鼠标移上图片时使其显示display:block,鼠标移到箭头上时改变透明度RGBA,使箭头颜色加深;

HTML代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>焦点轮播图</title>
<link rel="stylesheet" type="text/css" href="css/焦点轮播图.css">
</head>
<body>
<div id="container">
<div id="list" style="left: -600px">
<img src="images/5.jpg" alt="5"> <!-- 附属图实现无缝的滚动 -->
<img src="images/1.jpg" alt="1">
<img src="images/2.jpg" alt="2">
<img src="images/3.jpg" alt="3">
<img src="images/4.jpg" alt="4">
<img src="images/5.jpg" alt="5">
<img src="images/1.jpg" alt="5">
</div>
<div id="buttons">
<span index="1" class="on"></span>
<span index="2"></span>
<span index="3"></span>
<span index="4"></span>
<span index="5"></span>
</div>
<a href="javascript:;" id="prev" class="arrow">&lt;</a>
<a href="javascript:;" id="next" class="arrow">&gt;</a>
</div>
<script type="text/javascript" src="js/焦点轮播图.js"></script>
</body>
</html>

CSS代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
*{
margin: 0;
padding: 0;
text-decoration :none;
}
body{
padding: 20px;
}
#container{
width: 600px;
height: 400px;
position: relative;
border: 3px solid #333;
overflow: hidden;
}
#list{
height: 400px;
width: 4200px;
position: absolute;
z-index: 1; /*设置元素的堆叠顺序*/
}
#list img{
float: left;
}
#buttons{
height: 10px;
width: 100px;
z-index: 2;
bottom: 20px;
left: 250px;
position: absolute;
}
#buttons span {
cursor: pointer; /*规定要显示的光标的类型(手指)*/
float: left;
border: 1px solid #fff;
width: 10px;
height: 10px;
border-radius: 50%;
background: #333;
margin-right: 5px;
}
#buttons .on {
background: orangered;
}
.arrow {
cursor: pointer;
display: none; /*箭头隐藏*/
line-height: 39px;
text-align: center;
font-size: 36px;
font-weight: bold;
width: 40px; height: 40px;
position: absolute;
z-index: 2;
top: 180px;
background-color: RGBA(0,0,0,.3); /*透明度设置*/
color: #fff;
}
.arrow:hover {
background-color: RGBA(0,0,0,.7);
}
#container:hover .arrow {
display: block; /*箭头显示*/
}
#prev {
left: 20px;
}
#next {
right: 20px;
}

JS动画实现

箭头切换 -> 无限滚动 -> 按钮切换 -> 延迟切换 -> 自动播放

  1. 箭头切换

    • 整个页面加载window.onload,获取元素
    • 通过ID名获取页面中的元素(父容器、承载图片容器、圆点列表、箭头),赋值给一个变量
    • 添加一个时间绑定,点击箭头时实现图片的切换
    • 当点击右箭头时,改变left的值,向左移动,要减去一张图的宽度
    • 获取图片容器的值,list.style.left = 自身的值再减去一张图片的宽度
      注意要把等号后面字符串使用parseInt函数转换为数字才可以进行减法,减去的图片宽度要加px单位
    • 反方向同理,加上一张图片的宽度
    • 左右箭头的写法很相似,只是加减不一样,可以封装成一个函数,通过参数的正负值实现加减
  1. 无限滚动:弥补左右键切换的空白

    • 当前面的附属图比第一张大,最后一张附属图比最后一张小的时候,出现这两种情况时让它复位到真正的第一张或第五张图
    • 判断是否滚到了辅助图上,滚到了让它归位
    • 把常用的list.style.left,存到一个变量中,方便使用
    • 添加圆点的切换功能,创建一个变量来承载当前存储的第几张图片/显示第个圆点
    • 写一个函数,用来显示亮起小圆点的功能
      • 圆点是数组,所以创建的变量要减去1才能对应上要显示的圆点,让它亮起来添加class名
        <span index="1" class="on">
    • 再绑定事件中左箭头index要加一,右箭头要减一,调用圆点函数让它点击时显示,每次点击箭头的时候都要改变index的值,使它对应到正确的图片上,调用showButton亮起对应的圆点
    • 亮起自己的同时,让其他不亮,使用for循环,去掉所有的class,然后break退出循环,不再继续遍历元素节点
    • 箭头点击时,当圆点index大于5时,让它归位为1,小于1时,归位为5,不到5时加1
  1. 圆点按钮切换

    • 通过for循环遍历圆点,添加点击事件

    • 点击按钮时,取到index值,就可以知道当前点击的是第几个按钮,要显示第几张图片

    • 通过DOM2级方法getAttribute()获取到自定义(或自带)属性,为了计算再转换为数字var myIndex = parseInt(this.getAttribute('index'));

    • 通过新的值减去旧的值获取偏移量var offset = -600 * (myIndex - index);

    • 写一个判断,当这张图片是打开状态的,就什么都不做,用class=on来判断是否打开,return跳出,后面的代码不会再执行

      1
      2
      3
      4
      5
      6
      if (animated) {
      return;
      }
      if (this.className == 'on') {
      return;
      }
  1. 动画函数

    • 图片在一定时间内进行位移,要判断是否达到目标值,没有达到还要继续做位移
    • 声明一个变量用offset总共的偏移量除以次数(位移总时间time除以位移间隔时间inteval),求出每次移动多少var speed = offset / (time / inteval);
    • 判断speed小于0并且left值是否大于目标值newLeft或speed大于0并且left值小于目标值,这两种情况让它做位移speed > 0 && parseInt(list.style.left) < left) || (speed < 0 && parseInt(list.style.left) > left
    • 在判断中放入定时器setTimeout
      一个函数不停的在一定的条件之后调用自身这种做法叫做递归
  • 优化:声明一个变量,作为动画是否在运行的依据,开始状态为false表示没有运行var animated = false; //优化
  1. 自动播放

    • 鼠标移开时自动播放,鼠标移上去时停止,通过定时器setTimeoutclearTimeout来实现的
    • 设置定时器,让它隔几秒切换一次,相当于3秒钟调一次next.onclick(右箭头)事件
    • 自动切换需要写两个函数来控制自动切换,声明一个变量来存放定时器不给任何值
    • 鼠标移开时定时器执行,移上时清除定时器执行,要给整个容器加一个鼠标移入移开事件
    • 鼠标不做任何事情时让它自动播放,调用函数

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
window.onload = function() {
var container = document.getElementById('container');
var list = document.getElementById('list');
var buttons = document.getElementById('buttons').getElementsByTagName('span');
var prev = document.getElementById('prev');
var next = document.getElementById('next');
var index = 1; //索引
var len = 5;
var animated = false; //优化
var interval = 3000; //时间间隔
var timer;
function showButton() {
for (var i = 0; i < buttons.length; i++) {
if (buttons[i].className == 'on') {
buttons[i].className = '';
break;
}
}
buttons[index - 1].className = 'on';
} //按钮切换
next.onclick = function() {
if (animated) {
return;
}
if (index == 5) {
index = 1;
} else {
index += 1;
}
animate(-600);
showButton();
}//右切换
prev.onclick = function() {
if (animated) {
return;
}
if (index == 1) {
index = 5;
} else {
index -= 1;
}
animate(600);
showButton();
}//左切换
function play() {
timer = setTimeout(function() {
next.onclick();
play();
}, interval);
}
function stop() {
clearTimeout(timer);
}
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function() {
if (animated) {
return;
}
if (this.className == 'on') {
return;
}
var myIndex = parseInt(this.getAttribute('index'));
var offset = -600 * (myIndex - index);
animate(offset);
index = myIndex;
showButton();
}
}
function animate(offset) {
if (offset == 0) {
return;
}
animated = true;
var time = 300; //时间
var inteval = 10; //时间间隔
var speed = offset / (time / inteval); //速度
var left = parseInt(list.style.left) + offset; //改变值来实现滚动
var go = function() {
if ((speed > 0 && parseInt(list.style.left) < left) || (speed < 0 && parseInt(list.style.left) > left)) {
list.style.left = parseInt(list.style.left) + speed + 'px';
setTimeout(go, inteval);
} else {
list.style.left = left + 'px';
if (left > -200) {
list.style.left = -600 * len + 'px';
}
if (left < (-600 * len)) {
list.style.left = '-600px';
}
animated = false;
}
} //自动滚动
go();
}
container.onmouseover = stop();
container.onmouseout = play();
play();
}

总结

焦点轮播图的实现需要耐心分析原理,掌握焦点轮播图所需的技能点,从而通过代码实现。

先写出静态页面html+css,注意属性值的设置。再用js一步一步写出箭头切换、按钮切换的函数,学会设置和清除定时器、递归调用函数,实现自动滚动播放。

]]>
- - + + JavaScript + +
+ + HTML5音频解析与可视化 + /posts/fd5cbc55/ +

HTML5音频解析与可视化

基本结构

使用express 框架搭建后台基本结构

+ +

加载音乐并用ajax请求资源

加载音乐文件:

+
var lis = $("#list li");
for (var i = 0; i < list.length; i++) {
lis[i].onclick = function() {
for (var j = 0; j < lis.length; j++) {
lis[j].className = "";
}
this.className = "selected";
load("/media/" + this.title);
}
}
+

ajax加载资源

+
var xhr = new XMLHttpRequest();
xhr.abort();
xhr.open("GET", url);
xhr.responseType = "arraybuffer";
xhr.onload = function() {};
xhr.send();
+

Web Audio Api 关系图

1.webAudio-API

+

使用AudioContext解码

2.AudioContext

+

实现:

+
var ac = new(window.AudioContext || window.webkitAudioContext)();
ac.decodeAudioData(xhr.response, function(buffer) {
if (n != count) return;
var bufferSource = ac.createBufferSource();
bufferSource.buffer = buffer;
bufferSource.connect(gainNode);
//bufferSource.connect(ac.destination);
bufferSource[bufferSource.start ? "start" : "noteOn"](0);
suurce = bufferSource;
}
+

使用gainNode调节音量

3.GainNode

+

实现:

+
var gainNode = ac[ac.createGain ? "createGain" : "createGainNode"]();
gainNode.connect(ac.destination);
+

bufferSource连接gainNode

4.AudioBufferSourceNode

+

实现:

+
bufferSource.connect(gainNode);
function changeVolume(percent) {
gainNode.gain.value = percent * percent;
}
$("#volume")[0].onchange = function() {
changeVolume(this.value / this.max);
}
+

音乐播放逻辑问题

实现:

+
//音乐资源加载
var source = null;
//计数器
var count = 0;
var n = ++count;
source && source[source.stop ? "stop" : "noteOff"](); //默认为0
if (n != count) return;
+

分析音频资源

+

参考链接

+
+

5.AnalyserNode

+

实现:

+
var analyser=ac.createAnalyser();
analyser.fftSize=512;
analyser.connect(gainNode);
//bufferSource连接analyser
bufferSource.connect(analyser);
+

时时分析

+
function visualizer(){
var arr=new Uint8Array(analyser.frequencyBinCount);
requestAnimationFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame;
function v(){
analyser.getByteFrequencyData(arr);
}
requestAnimationFrame(v);
}
visualizer();
+

音乐数据可视化

使用canvas画图进行可视化

+
//canvas画图(柱状)
var box = $("#box")[0];
var height, width;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
box.appendChild(canvas);
function resize() {
height = box.clientHeight;
width = box.clientWidth;
canvas.height = height;
canvas.width = width;
var line = ctx.createLinearGradient(0, 0, 0, height);
line.addColorStop(0, "red");
line.addColorStop(0.5, "yello");
line.addColorStop(1, "green");
ctx.fillstyle = line;
}
resize();
window.onresize = resize;
function draw(arr) {
ctx.clearRect(0,0,width,height);
var w = width / size;
for (var i = 0; i < size; i++) {
var h = arr[i] / 256 * height;
ctx.fillRect(w * i, height - h, w * 0.6, h);
}
}
+]]>
- - web前端 - + web前端 - - - - - JavaScript - - - -
- - - - - HTML5音频解析与可视化 - - /posts/fd5cbc55/ - -

HTML5音频解析与可视化

基本结构

使用express 框架搭建后台基本结构

加载音乐并用ajax请求资源

加载音乐文件:

1
2
3
4
5
6
7
8
9
10
11
var lis = $("#list li");
for (var i = 0; i < list.length; i++) {
lis[i].onclick = function() {
for (var j = 0; j < lis.length; j++) {
lis[j].className = "";
}
this.className = "selected";
load("/media/" + this.title);
}
}

ajax加载资源

1
2
3
4
5
6
var xhr = new XMLHttpRequest();
xhr.abort();
xhr.open("GET", url);
xhr.responseType = "arraybuffer";
xhr.onload = function() {};
xhr.send();

Web Audio Api 关系图

1.webAudio-API

使用AudioContext解码

2.AudioContext

实现:

1
2
3
4
5
6
7
8
9
10
var ac = new(window.AudioContext || window.webkitAudioContext)();
ac.decodeAudioData(xhr.response, function(buffer) {
if (n != count) return;
var bufferSource = ac.createBufferSource();
bufferSource.buffer = buffer;
bufferSource.connect(gainNode);
//bufferSource.connect(ac.destination);
bufferSource[bufferSource.start ? "start" : "noteOn"](0);
suurce = bufferSource;
}

使用gainNode调节音量

3.GainNode

实现:

1
2
var gainNode = ac[ac.createGain ? "createGain" : "createGainNode"]();
gainNode.connect(ac.destination);

bufferSource连接gainNode

4.AudioBufferSourceNode

实现:

1
2
3
4
5
6
7
8
9
bufferSource.connect(gainNode);
function changeVolume(percent) {
gainNode.gain.value = percent * percent;
}
$("#volume")[0].onchange = function() {
changeVolume(this.value / this.max);
}

音乐播放逻辑问题

实现:

1
2
3
4
5
6
7
8
9
10
11
//音乐资源加载
var source = null;
//计数器
var count = 0;
var n = ++count;
source && source[source.stop ? "stop" : "noteOff"](); //默认为0
if (n != count) return;

分析音频资源

参考链接

5.AnalyserNode

实现:

1
2
3
4
5
6
var analyser=ac.createAnalyser();
analyser.fftSize=512;
analyser.connect(gainNode);
//bufferSource连接analyser
bufferSource.connect(analyser);

时时分析

1
2
3
4
5
6
7
8
9
10
11
function visualizer(){
var arr=new Uint8Array(analyser.frequencyBinCount);
requestAnimationFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame;
function v(){
analyser.getByteFrequencyData(arr);
}
requestAnimationFrame(v);
}
visualizer();

音乐数据可视化

使用canvas画图进行可视化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//canvas画图(柱状)
var box = $("#box")[0];
var height, width;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
box.appendChild(canvas);
function resize() {
height = box.clientHeight;
width = box.clientWidth;
canvas.height = height;
canvas.width = width;
var line = ctx.createLinearGradient(0, 0, 0, height);
line.addColorStop(0, "red");
line.addColorStop(0.5, "yello");
line.addColorStop(1, "green");
ctx.fillstyle = line;
}
resize();
window.onresize = resize;
function draw(arr) {
ctx.clearRect(0,0,width,height);
var w = width / size;
for (var i = 0; i < size; i++) {
var h = arr[i] / 256 * height;
ctx.fillRect(w * i, height - h, w * 0.6, h);
}
}
]]>
- - + + HTML5 + +
+ + Mac转Windows的拯救指南 + /posts/143a0a72/ +

Mac转Windows的拯救指南

+

假期使用Mac开发,目前转Windows开发学习,体会了Mac上高效率的快捷键之后,感觉用鼠标点来点去很麻烦,将一些小工具使用,来提高效率。这只是给新手介绍,大神请绕过。

+
+

下面开始介绍一些工具来拯救Mac党

+

1.Chocolatey

Chocolatey是一个Windows上的包管理器,类似于linux上的yum和 apt-get。 你可以在其官方网站上查看具体的使用说明。一般的安装步骤应该是下面这样:

+

CMD

+
@powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin
+

Powershell

+
Set-ExecutionPolicy Bypass; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
+

一般来说,使用Chocolatey来安装软件的时候,需要以管理员的身份来运行命令提示符窗口。chocolatey的网站可能在国内访问困难,导致上述安装命令无法正常完成。请使用科学上网。

+ +

2.Cmder or Powershell or Git

Cmder是一个替代原机自带cmd的命令行,可以配置,有快捷键,常用的Tab补全,集成Git等。

+

Powershell是微软公司开发的任务自动化和管理框架。功能强大,背后还有牛逼的老爹支持,命令与cmd有所不同,老司机可以玩玩。

+

Git是一个自由开源的版本控制工具,它在Windows下有相应的命令行工具,命令与linux命令相同,学习了linux,可以很快上手,对于前端来说,这个我觉得是比较方便的,但是,有时候也会抽风。

+

3.Listary or Wox

Listary是一个文件浏览增强工具。和Mac下的Alfred工具差不多,个人使用free版本即可,自定义快捷键,笔记本可以脱离鼠标,直接使用键盘和触摸板。

+

Wox是一个有效的搜索工具。

+
    +
  • 可以文件和应用搜索
  • +
  • 有插件支持
  • +
  • 主题修改
  • +
  • web快捷键快速查找,自定义搜索引擎
  • +
+

4.Total Commander

Total Commander是一款应用于 Windows 平台的文件管理器 ,它包含两个并排的窗口,这种设计可以让用户方便地对不同位置的“文件或文件夹”进行操作,例如复制、移动、删除、比较等,相对 Windows 资源管理器而言方便很多,极大地提高了文件操作的效率,被广大软件爱好者亲切地简称为:TC 。

+

它拥有文件快速预览、快速搜索、多标签、文件比较、批量重命名、FTP 客户端等诸多实用的功能,并可通过大量的插件进行个性化配置。

+

官网介绍不是很详细,可查看维基百科的介绍,TC

+

5.FastStone Screen Capture or Snipaste

FastStone Screen Capture是一个轻量的截屏工具,很老但是很强大。

+

Snipaste,免费,免安装,可定制。

+

6.NotePad++

NotePad++,替代记事本的轻量级记事本,原本的记事本会有很多弊病,编码格式不是UTF-8。NotePad++解决了这些麻烦,还可以自定义设置,完全变成编辑器,有提示。

+

7.Xshell

Xshell是一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议。Xshell 通过互联网到远程主机的安全连接以及它创新性的设计和特色帮助用户在复杂的网络环境中享受他们的工作。 Xshell可以在Windows界面下用来访问远端不同系统下的服务器,从而比较好的达到远程控制终端的目的。

+]]>
- - web前端 - + 工具 - - - - - HTML5 - - - -
- - - - - Mac转Windows的拯救指南 - - /posts/143a0a72/ - -

Mac转Windows的拯救指南

假期使用Mac开发,目前转Windows开发学习,体会了Mac上高效率的快捷键之后,感觉用鼠标点来点去很麻烦,将一些小工具使用,来提高效率。这只是给新手介绍,大神请绕过。

下面开始介绍一些工具来拯救Mac党

1.Chocolatey

Chocolatey是一个Windows上的包管理器,类似于linux上的yum和 apt-get。 你可以在其官方网站上查看具体的使用说明。一般的安装步骤应该是下面这样:

CMD

1
@powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin

Powershell

1
Set-ExecutionPolicy Bypass; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

一般来说,使用Chocolatey来安装软件的时候,需要以管理员的身份来运行命令提示符窗口。chocolatey的网站可能在国内访问困难,导致上述安装命令无法正常完成。请使用科学上网。

2.Cmder or Powershell or Git

Cmder是一个替代原机自带cmd的命令行,可以配置,有快捷键,常用的Tab补全,集成Git等。

Powershell是微软公司开发的任务自动化和管理框架。功能强大,背后还有牛逼的老爹支持,命令与cmd有所不同,老司机可以玩玩。

Git是一个自由开源的版本控制工具,它在Windows下有相应的命令行工具,命令与linux命令相同,学习了linux,可以很快上手,对于前端来说,这个我觉得是比较方便的,但是,有时候也会抽风。

3.Listary or Wox

Listary是一个文件浏览增强工具。和Mac下的Alfred工具差不多,个人使用free版本即可,自定义快捷键,笔记本可以脱离鼠标,直接使用键盘和触摸板。

Wox是一个有效的搜索工具。

  • 可以文件和应用搜索
  • 有插件支持
  • 主题修改
  • web快捷键快速查找,自定义搜索引擎

4.Total Commander

Total Commander是一款应用于 Windows 平台的文件管理器 ,它包含两个并排的窗口,这种设计可以让用户方便地对不同位置的“文件或文件夹”进行操作,例如复制、移动、删除、比较等,相对 Windows 资源管理器而言方便很多,极大地提高了文件操作的效率,被广大软件爱好者亲切地简称为:TC 。

它拥有文件快速预览、快速搜索、多标签、文件比较、批量重命名、FTP 客户端等诸多实用的功能,并可通过大量的插件进行个性化配置。

官网介绍不是很详细,可查看维基百科的介绍,TC

5.FastStone Screen Capture or Snipaste

FastStone Screen Capture是一个轻量的截屏工具,很老但是很强大。

Snipaste,免费,免安装,可定制。

6.NotePad++

NotePad++,替代记事本的轻量级记事本,原本的记事本会有很多弊病,编码格式不是UTF-8。NotePad++解决了这些麻烦,还可以自定义设置,完全变成编辑器,有提示。

7.Xshell

Xshell是一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议。Xshell 通过互联网到远程主机的安全连接以及它创新性的设计和特色帮助用户在复杂的网络环境中享受他们的工作。 Xshell可以在Windows界面下用来访问远端不同系统下的服务器,从而比较好的达到远程控制终端的目的。

]]>
- - + + Mac + Windons + +
+ + MapReduce初探 + /posts/e6939326/ +

MapReduce初探

MapReduce是一个用于处理海量数据的分布式计算框架

+

MapReduce解决的问题:

+
    +
  • 数据分布式存储
  • +
  • 作业调度
  • +
  • 容错
  • +
  • 机器间通信
  • +
+ +

MapReduce存储:HDFS

+
    +
  • 系统可靠性
  • +
  • 可扩展性
  • +
  • 并发处理
  • +
+

Alt text

+

MapReduce思想:分治

+
    +
  • 分解

    +
  • +
  • 求解

    +
  • +
  • 合并

    +
  • +
  • 分:map

    +

    把复杂的问题分解为若干简单的任务

    +
  • +
  • 合:reduce

    +
  • +
+

MapReduce执行流程

Alt text

+

Alt text

+

Alt text

+

Alt text

+

Alt text

+

Alt text

+

Alt text

+

Alt text

+

Alt text

+

Alt text

+

Alt text

+

Alt text

+

Alt text

+

Alt text

+

实例

WordCount

Alt text

+

应用

    +
  • 数据统计
      +
    • A/B test的需要,实验和对照统计对比各个指标
    • +
    • 统计广告每天的展示、点击和消费总量
    • +
    • 统计视频在一段时间内展示和点击数量,CTR指标
    • +
    +
  • +
+
    +
  • 数据过滤
      +
    • 从日志中找到某一个条件数据
    • +
    • 除去非法数据,保留合法数据
    • +
    • 数据格式整理
    • +
    +
  • +
+
    +
  • 同类汇聚
      +
    • 多份日志中,相同时间点、用户行为日志混合
    • +
    • 类表格文件存储中,相同主键拼接相关的属性
    • +
    • 历史的主数据与新增、修改数据合并
    • +
    +
  • +
+
    +
  • 全局排序
      +
    • 混合日志按时间排序
    • +
    • 多个字段排序
    • +
    • 数据按名称排序
    • +
    +
  • +
+
    +
  • 容错框架
      +
    • 易出错的服务,大数值计算
    • +
    • 计算规模经常变化调整的服务
    • +
    • 单进程程序。迅速提升执行计算效率
    • +
    +
  • +
+]]>
- - 工具 - + 大数据 - - - - - Mac - - Windons - - - -
- - - - - MapReduce初探 - - /posts/e6939326/ - -

MapReduce初探

MapReduce是一个用于处理海量数据的分布式计算框架

MapReduce解决的问题:

  • 数据分布式存储
  • 作业调度
  • 容错
  • 机器间通信

MapReduce存储:HDFS

  • 系统可靠性
  • 可扩展性
  • 并发处理

Alt text

MapReduce思想:分治

  • 分解

  • 求解

  • 合并

  • 分:map

    把复杂的问题分解为若干简单的任务

  • 合:reduce

MapReduce执行流程

Alt text

Alt text

Alt text

Alt text

Alt text

Alt text

Alt text

Alt text

Alt text

Alt text

Alt text

Alt text

Alt text

Alt text

实例

WordCount

Alt text

应用

  • 数据统计
    • A/B test的需要,实验和对照统计对比各个指标
    • 统计广告每天的展示、点击和消费总量
    • 统计视频在一段时间内展示和点击数量,CTR指标
  • 数据过滤
    • 从日志中找到某一个条件数据
    • 除去非法数据,保留合法数据
    • 数据格式整理
  • 同类汇聚
    • 多份日志中,相同时间点、用户行为日志混合
    • 类表格文件存储中,相同主键拼接相关的属性
    • 历史的主数据与新增、修改数据合并
  • 全局排序
    • 混合日志按时间排序
    • 多个字段排序
    • 数据按名称排序
  • 容错框架
    • 易出错的服务,大数值计算
    • 计算规模经常变化调整的服务
    • 单进程程序。迅速提升执行计算效率
]]>
- - + + MapReduce + +
+ + 数据结构与算法JavaScript学习(二) + /posts/db1de468/ +

数据结构与算法JavaScript学习(二)

搜索算法

顺序或线性搜索

function ArrayList(){
var array=[];
this.insert=function(item){
array.push(item);
};
this.toString=function(){
return array.join();
};
//顺序搜索
this.sequentialSearch=function (item) {
for (var i = 0; i < array.length; i++) {
if (item===array[i]) {
return i;
}
}
return -1;
};
}
+ +

二分搜索

function ArrayList(){
var array=[];
this.insert=function(item){
array.push(item);
};
this.toString=function(){
return array.join();
};
//快速排序:分治递归
this.quickSort=function () {
quick(array,0,array.length-1);
};
//快排
var quick=function (array,left,right) {
var index;
if (array.length>1) {
index=partition(array,left,right);
if (left<index-1) {
quick(array,left,index-1);
}
if (index<right) {
quick(array,index,right);
}
}
};
//划分过程
var partition=function(array,left,right){
var pivot=array[Math.floor((right+left)/2)],i=left,j=right;//选主元
while (i<=j) {
while (array[i]<pivot) {
i++;
}
while (array[j]>pivot) {
j--;
}
if (i<=j) {
swapQuickStort(array,i,j);
i++;
j--;
}
}
return i;
};
//交换数组元素
var swapQuickStort=function (array,index1,index2) {
var aux=array[index1];
array[index1]=array[index2];
array[index2]=aux;
};
//二分搜索
this.binarySearch=function (item) {
this.quickSort();//快速排序
var low=0,high=array.length-1,mid,element;
while (low<=high) {
mid=Math.floor((low+high)/2);
element=array[mid];
if (element<item) {
low=mid+1;
}else if (element>item) {
high=mid-1;
}else {
return mid;
}
}
return -1;
};
}
+

算法思想

递归

//斐波那契数列:递归
function fibonacci(num) {
if (num===1||num===2) {
return 1;
}
return fibonacci(num-1)+fibonacci(num-2);
}
+

非递归

//斐波那契数列:非递归
function fib(num) {
var n1=1,n2=1,n=1;
for (var i = 3; i <= num; i++) {
n=n1+n2;
n1=n2;
n2=n;
}
return n;
}
+

动态规划

//动态规划:将大问题转化成小问题
//最少硬币找零问题:找到n所需的最小硬币数
function dpMinCoinChange(coins) {
var coins=coins;
var cache={};
this.makeChange=function (amount) {
var me=this;
if (!amount) {//判断为正
return [];
}
if (cache[amount]) {//判断是否有缓存
return cache[amount];
}
var min=[],newMin,newAmount;
for (var i = 0; i < coins.length; i++) {//对每个面额计算
var coin=coins[i];
newAmount=amount-coin;
if (newAmount>=0) {
newMin=me.makeChange(newAmount);
}
if (newAmount>=0 && (newMin.length<min.length-1 || !min.length)
&& (newMin.length || !newAmount)) {
//判断newAmount是否有效,最小硬币数是否最优,newMin和newAmount是否合理
min=[coin].concat(newMin);
console.log('new Min '+min+ ' for '+amount);
}
}
return (cache[amount]=min);
}
}
+

贪心策略

//贪心算法:近似求解,通过局部最优达到全局最优
//最少硬币找零问题:找到n所需的最小硬币数
function txMinCoinChange(coins){
var coins=coins;
this.makeChange=function(amount){
var change=[],total=0;
for (var i = coins.length; i >= 0; i--) {//对每个面额从大面额开始,从大到小依次
var coin=coins[i];
while (total+coin<=amount) {
change.push(coin);
total+=coin;
}
}
return change;
}
}
+]]>
- - 大数据 - + web前端 - - - - - MapReduce - - - -
- - - - - 数据结构与算法JavaScript学习(二) - - /posts/db1de468/ - -

数据结构与算法JavaScript学习(二)

搜索算法

顺序或线性搜索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function ArrayList(){
var array=[];
this.insert=function(item){
array.push(item);
};
this.toString=function(){
return array.join();
};
//顺序搜索
this.sequentialSearch=function (item) {
for (var i = 0; i < array.length; i++) {
if (item===array[i]) {
return i;
}
}
return -1;
};
}

二分搜索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
function ArrayList(){
var array=[];
this.insert=function(item){
array.push(item);
};
this.toString=function(){
return array.join();
};
//快速排序:分治递归
this.quickSort=function () {
quick(array,0,array.length-1);
};
//快排
var quick=function (array,left,right) {
var index;
if (array.length>1) {
index=partition(array,left,right);
if (left<index-1) {
quick(array,left,index-1);
}
if (index<right) {
quick(array,index,right);
}
}
};
//划分过程
var partition=function(array,left,right){
var pivot=array[Math.floor((right+left)/2)],i=left,j=right;//选主元
while (i<=j) {
while (array[i]<pivot) {
i++;
}
while (array[j]>pivot) {
j--;
}
if (i<=j) {
swapQuickStort(array,i,j);
i++;
j--;
}
}
return i;
};
//交换数组元素
var swapQuickStort=function (array,index1,index2) {
var aux=array[index1];
array[index1]=array[index2];
array[index2]=aux;
};
//二分搜索
this.binarySearch=function (item) {
this.quickSort();//快速排序
var low=0,high=array.length-1,mid,element;
while (low<=high) {
mid=Math.floor((low+high)/2);
element=array[mid];
if (element<item) {
low=mid+1;
}else if (element>item) {
high=mid-1;
}else {
return mid;
}
}
return -1;
};
}

算法思想

递归

1
2
3
4
5
6
7
8
//斐波那契数列:递归
function fibonacci(num) {
if (num===1||num===2) {
return 1;
}
return fibonacci(num-1)+fibonacci(num-2);
}

非递归

1
2
3
4
5
6
7
8
9
10
//斐波那契数列:非递归
function fib(num) {
var n1=1,n2=1,n=1;
for (var i = 3; i <= num; i++) {
n=n1+n2;
n1=n2;
n2=n;
}
return n;
}

动态规划

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//动态规划:将大问题转化成小问题
//最少硬币找零问题:找到n所需的最小硬币数
function dpMinCoinChange(coins) {
var coins=coins;
var cache={};
this.makeChange=function (amount) {
var me=this;
if (!amount) {//判断为正
return [];
}
if (cache[amount]) {//判断是否有缓存
return cache[amount];
}
var min=[],newMin,newAmount;
for (var i = 0; i < coins.length; i++) {//对每个面额计算
var coin=coins[i];
newAmount=amount-coin;
if (newAmount>=0) {
newMin=me.makeChange(newAmount);
}
if (newAmount>=0 && (newMin.length<min.length-1 || !min.length)
&& (newMin.length || !newAmount)) {
//判断newAmount是否有效,最小硬币数是否最优,newMin和newAmount是否合理
min=[coin].concat(newMin);
console.log('new Min '+min+ ' for '+amount);
}
}
return (cache[amount]=min);
}
}

贪心策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//贪心算法:近似求解,通过局部最优达到全局最优
//最少硬币找零问题:找到n所需的最小硬币数
function txMinCoinChange(coins){
var coins=coins;
this.makeChange=function(amount){
var change=[],total=0;
for (var i = coins.length; i >= 0; i--) {//对每个面额从大面额开始,从大到小依次
var coin=coins[i];
while (total+coin<=amount) {
change.push(coin);
total+=coin;
}
}
return change;
}
}
]]>
- - + + JavaScript + +
+ + MongoDB基础学习 + /posts/8c3b0bac/ +

MongoDB基础学习

+

MongoDB是一个跨平台,面向文档的数据库,提供高性能,高可用性和易于扩展,总结知识点分享给与我一样刚入门MongoDB的人。

+
+

基本概念

    +
  • 数据库:数据库是一个集合的物理容器。每个数据库获取其自己设定在文件系统上的文件。一个单一的MongoDB服务器通常有多个数据库
  • +
  • 集合:集合是一组MongoDB的文件。它与一个RDBMS表是等效的。一个集合存在于数据库中。集合不强制执行模式。集合中的文档可以有不同的字段。
  • +
  • 文档:文档是一组键值对。文档具有动态模式。动态模式是指,在同一个集合的文件不必具有相同一组集合的文档字段或结构,并且相同的字段可以保持不同类型的数据。
  • +
+ +
    +
  • 文档是MongoDB中数据的基本单元
  • +
  • 在MongoDB中,一个MongoDB实例可以承载多个数据库,每个数据库拥有0或多个集合,一个集合拥有多个文档
  • +
  • 在同一个MongoDB服务器上存放多个应用那个程序或用户的数据,需要使用不同的数据库
  • +
  • 使用BSON格式
  • +
+

使用MongoDB在哪些场景

    +
  • 大而复杂的数据
  • +
  • 移动和社会基础设施数据
  • +
  • 内容管理和交付
  • +
  • 用户数据管理
  • +
  • 数据中心
  • +
+

初始化的数据库

    +
  • admin:root数据库,有数据库所以权限
  • +
  • local:存储所以本地集合
  • +
  • config:存储分片信息
  • +
+

基本数据类型

    +
  • null:空或不存在
  • +
  • 布尔型:true或false
  • +
  • 数值:默认64位浮点型数值
  • +
  • 字符串:UTF-8
  • +
  • 日期:自新世纪以来经过的毫秒,不存储时区
  • +
  • 正则表达式:与js语法相同
  • +
  • 数组:数据列表或数据集
  • +
  • 内嵌文档:对象嵌套
  • +
  • 对象
      +
    • 对象id是一个12字节的ID,是一个由24个十六进制数字组成的字符串,作为文档唯一标识,一秒钟最多允许每个进程拥有2563个不同的ObjectId
    • +
    • ObjectId前四个字节是从标准纪元开始的时间戳,单位为秒
    • +
    • 接下来3个字节是所在主机的唯一标识符,机器主机名的散列值
    • +
    • 接下来2个字节来自产生ObjectId的进程的进程标识符PID
    • +
    • 最后3个字节是一个自动增加的计数器
    • +
    +
  • +
  • 二进制数据
  • +
  • 代码
  • +
+

MongoDB shell

    +
  • 启动时会连到test数据库,并将数据库连接赋值给全局变量db

    +
  • +
  • 连接到不同的数据库或服务器

    +
  • +
+
mongo --nodb
connect=new Mongo("host:27017")
db=connect.getDB("myDB")
+
    +
  • 帮助

    +
      +
    • help
    • +
    • db.foo.update,方法不加括号可查看相应函数的源码
    • +
    +
  • +
  • 创建.mongorc.js

    +
      +
    • 频繁加载的脚本
    • +
    • 移除比较危险的shell辅助函数
    • +
    • 指定--norc,可以禁止加载.mongorc.js
    • +
    +
  • +
  • 定制shell提示:将prompt变量设为一个字符串或函数

    +
  • +
  • 编辑符合变量:设置EDITOR

    +
  • +
+

四个基本操作:创建、读取、更新、删除(CRUD)

创建

    +
  • 单个插入:insert
  • +
  • 批量插入:batchInsert
  • +
+

删除

    +
  • 删除文档:remove,可接受一个查询文档作为参数
  • +
  • 删除集合:drop,不能指定条件
  • +
+

更新

    +
  • update:必须接受两个参数,第一个匹配待更新文档,第二个是修改器文档。接受第三个参数,若为true,则表示这是upsert。接受第四个参数,若为true,则表示更新所有匹配的文档。
  • +
  • 原子性的更新修改器
      +
    • $set:指定一个字段的值
    • +
    • $unset:删除指定键
    • +
    • $inc:增加已有键的值,不存在则创建,只能用于整型、长整型或双精度浮点型的值
    • +
    • $push:向已有数组末尾加入一个元素
        +
      • $each:通过一次$push操作添加多个值
      • +
      • $slice:设置最大长度,必须为负整数,相当于建立队列,保留最后的元素
      • +
      • $sort:清理元素
      • +
      +
    • +
    • $addToSet:添加新数据,可以避免重复
    • +
    • $pop:可以从数组任何一端删除元素
    • +
    +
  • +
  • $pull:删除所有匹配的文档
  • +
  • upsert:若未找到符合更新条件的文档,则以此为条件创建新文档;若找到相应文档,正常更新。可用于创建又可用于更新。
  • +
+

读取

find和findOne

+
    +
  • 第一个参数用于指定查询条件
  • +
  • 第二个参数指定想要返回的键

    +
  • +
  • 查询条件

    +
      +
    • $lt,$lte,$gt,$gte,$ne对应小于、小于等于、大于、大于等于、不等于
    • +
    • $in:用来查询一个键的多个值
    • +
    • $or:在多个键中查询任意给定值

      +
      db.raffle.find({"$or":[{"tricket_no":{"in":[755,542,390]}},{"winner":true}]})
      +
    • +
    • $not:用来查询与特定模式不匹配的文档

      +
    • +
    • $exists:判定键值是否存在
    • +
    • $maxscan:指定本次查询文档数量的上限
    • +
    • $min:强制指定下边界
    • +
    • $max:强制指定上边界
    • +
    +
  • +
  • $showDiskLoc:用于显示结果在磁盘的位置

    +
  • +
  • 数组查询

    +
      +
    • $all:通过多个元素匹配数组
    • +
    • $size:查询特定长度的数组
    • +
    • $slice:返回某个键匹配的数组元素的一个子集
    • +
    • $elemMatch:指定一组添加,只可用于数组
    • +
    +
  • +
  • 查询函数

    +
      +
    • limit:限制返回数量
    • +
    • skip:忽略一定数量的结果
    • +
    • sort:接受一个对象作为参数,键为文档键名,值为排序方向(1为升序,-1为降序)
    • +
    +
  • +
+]]>
- - web前端 - + 数据库 - - - - - JavaScript - - - -
- - - - - MongoDB基础学习 - - /posts/8c3b0bac/ - -

MongoDB基础学习

MongoDB是一个跨平台,面向文档的数据库,提供高性能,高可用性和易于扩展,总结知识点分享给与我一样刚入门MongoDB的人。

基本概念

  • 数据库:数据库是一个集合的物理容器。每个数据库获取其自己设定在文件系统上的文件。一个单一的MongoDB服务器通常有多个数据库
  • 集合:集合是一组MongoDB的文件。它与一个RDBMS表是等效的。一个集合存在于数据库中。集合不强制执行模式。集合中的文档可以有不同的字段。
  • 文档:文档是一组键值对。文档具有动态模式。动态模式是指,在同一个集合的文件不必具有相同一组集合的文档字段或结构,并且相同的字段可以保持不同类型的数据。
  • 文档是MongoDB中数据的基本单元
  • 在MongoDB中,一个MongoDB实例可以承载多个数据库,每个数据库拥有0或多个集合,一个集合拥有多个文档
  • 在同一个MongoDB服务器上存放多个应用那个程序或用户的数据,需要使用不同的数据库
  • 使用BSON格式

使用MongoDB在哪些场景

  • 大而复杂的数据
  • 移动和社会基础设施数据
  • 内容管理和交付
  • 用户数据管理
  • 数据中心

初始化的数据库

  • admin:root数据库,有数据库所以权限
  • local:存储所以本地集合
  • config:存储分片信息

基本数据类型

  • null:空或不存在
  • 布尔型:true或false
  • 数值:默认64位浮点型数值
  • 字符串:UTF-8
  • 日期:自新世纪以来经过的毫秒,不存储时区
  • 正则表达式:与js语法相同
  • 数组:数据列表或数据集
  • 内嵌文档:对象嵌套
  • 对象
    • 对象id是一个12字节的ID,是一个由24个十六进制数字组成的字符串,作为文档唯一标识,一秒钟最多允许每个进程拥有2563个不同的ObjectId
    • ObjectId前四个字节是从标准纪元开始的时间戳,单位为秒
    • 接下来3个字节是所在主机的唯一标识符,机器主机名的散列值
    • 接下来2个字节来自产生ObjectId的进程的进程标识符PID
    • 最后3个字节是一个自动增加的计数器
  • 二进制数据
  • 代码

MongoDB shell

  • 启动时会连到test数据库,并将数据库连接赋值给全局变量db

  • 连接到不同的数据库或服务器

1
2
3
mongo --nodb
connect=new Mongo("host:27017")
db=connect.getDB("myDB")
  • 帮助

    • help
    • db.foo.update,方法不加括号可查看相应函数的源码
  • 创建.mongorc.js

    • 频繁加载的脚本
    • 移除比较危险的shell辅助函数
    • 指定--norc,可以禁止加载.mongorc.js
  • 定制shell提示:将prompt变量设为一个字符串或函数

  • 编辑符合变量:设置EDITOR

四个基本操作:创建、读取、更新、删除(CRUD)

创建

  • 单个插入:insert
  • 批量插入:batchInsert

删除

  • 删除文档:remove,可接受一个查询文档作为参数
  • 删除集合:drop,不能指定条件

更新

  • update:必须接受两个参数,第一个匹配待更新文档,第二个是修改器文档。接受第三个参数,若为true,则表示这是upsert。接受第四个参数,若为true,则表示更新所有匹配的文档。
  • 原子性的更新修改器
    • $set:指定一个字段的值
    • $unset:删除指定键
    • $inc:增加已有键的值,不存在则创建,只能用于整型、长整型或双精度浮点型的值
    • $push:向已有数组末尾加入一个元素
      • $each:通过一次$push操作添加多个值
      • $slice:设置最大长度,必须为负整数,相当于建立队列,保留最后的元素
      • $sort:清理元素
    • $addToSet:添加新数据,可以避免重复
    • $pop:可以从数组任何一端删除元素
  • $pull:删除所有匹配的文档
  • upsert:若未找到符合更新条件的文档,则以此为条件创建新文档;若找到相应文档,正常更新。可用于创建又可用于更新。

读取

find和findOne

  • 第一个参数用于指定查询条件
  • 第二个参数指定想要返回的键

  • 查询条件

    • $lt,$lte,$gt,$gte,$ne对应小于、小于等于、大于、大于等于、不等于
    • $in:用来查询一个键的多个值
    • $or:在多个键中查询任意给定值

      1
      db.raffle.find({"$or":[{"tricket_no":{"in":[755,542,390]}},{"winner":true}]})
    • $not:用来查询与特定模式不匹配的文档

    • $exists:判定键值是否存在
    • $maxscan:指定本次查询文档数量的上限
    • $min:强制指定下边界
    • $max:强制指定上边界
  • $showDiskLoc:用于显示结果在磁盘的位置

  • 数组查询

    • $all:通过多个元素匹配数组
    • $size:查询特定长度的数组
    • $slice:返回某个键匹配的数组元素的一个子集
    • $elemMatch:指定一组添加,只可用于数组
  • 查询函数

    • limit:限制返回数量
    • skip:忽略一定数量的结果
    • sort:接受一个对象作为参数,键为文档键名,值为排序方向(1为升序,-1为降序)
]]>
- - + + MongoDB + +
+ + FreeCodeCamp学习笔记(二) + /posts/e20ef482/ +

FreeCodeCamp学习笔记(二)

基本概念

软件概念

    +
  • 软件是程序或在硬件上运行的程序,写入硬件的代码,两种软件类型是操作系统和应用软件。
  • +
  • 有三个主要的操作系统:Windows,Mac和Linux。
  • +
  • 应用范围包括所有其他软件,如Web浏览器,游戏,还有像Photoshop,查看邮件,编辑文档的软件等。
  • +
+

CDN

    +
  • 内容传递网络(CDN)是一种分布式服务器(网络),基于用户的地理位置向用户分发网页和其他Web内容,网页和内容分发服务器的起源。
  • +
  • CDN的目标是建立更高质量的网络连接。
  • +
  • CDNs通过为用户和用户目标站点之间建立快速通道或提供更快的建立在其他服务器上的镜像站点来达成目标。
  • +
  • 这个概念和这种类型的服务不是创新型的想法,但是它正使互联网更加普及。
  • +
  • 网站付费使用CDN服务,而CDN反过来you向因特网提供商付费来使用他们的服务和数据。
  • +
  • 谷歌托管库就是一种CDNs : developers.google.com/speed/libraries/#jquery
  • +
  • 谷歌托管那些(常用的)库,比起你自己(在自己的服务器上)部署这些库,你的用户就可以更快的访问到它。
  • +
  • 有可能的话,用户浏览器甚至会存储已经访问过的网站的缓存。
  • +
+ +

模拟与数字转换和压缩

    +
  • 一个模拟声波可能看起来像任何东西,例子中它是一条波浪线。
  • +
  • 计算机采集和测量很多很多不同的点。把他们转化为数字,这就是所谓的采样。之后,计算机可以使用这些数字,并再次把它们变成声音。
  • +
  • 压缩的好处是,它是一个更小的文件:它更容易储存,它更容易发送给其他人,它只是占用更少的空间。
  • +
  • 压缩声音的一种常用方法是以更低的频率采样。
  • +
  • 另一种方式是,它从一个中点而不是0开始采样,所以所采集的数字更小。
  • +
  • 在图像中,它是通过测量一组16个的像素来压缩,而不是独立的。
  • +
  • 视频中减掉的部分是你想使用一个高质量的数字文件,但当你在压缩时,你需要决定压缩到何种程度以确保用户仍然有最好的体验。
  • +
+

联网

    +
  • 路由器是连接不同的小范围网络的东西。
  • +
+
我想打个比方:我是一名教师,我在一所学校工作。
假如说我有一个包,并且我需要把它送给我在民政事务处工作的人。
我不知道她在哪里,我不知道她的办公室所在地,但我知道她的名字。
我找我的秘书,像我的第一台路由器,我说"嘿,我需要找在民政事务处的某某,你能帮帮我吗?",她会说:"当然,我不知道她的办公室准确位置,但我知道,下一步,我可以找到她所在的区域。"
于是,她继续并将其它发送至到民政事务处的秘书,下一个路由器。
那秘书不知道我是谁或者我在哪里,但她看到包装上的名称,知道结束位置。
我想要去表达的是每个路由器只需要知道自己的小网,就在它旁边的站点。
它不必知道整个互联网,但只是它自己的连接。
它可以获取信息并说,好吧,我不知道确切位置这回事,但我会在正确的方向传递下去吧。
这就是它所需要做的事。
+
    +
  • 路由器可以是不同的尺寸,不同容量,但他们做的是知道自己的邻居,获得信息,并传递向正确的方向。
  • +
  • 路由器甚至不必须有完整的包的信息。
  • +
  • 如果一台电脑正试图将信息发送到另一个时,数据可能会在不同的路由器之间分开,但是这没问题。计算机仍然知道如何正确地把信息重新组合到一起。
  • +
  • 所发送信息的小碎片被称为数据包。包实际上是一小段二进制代码。
  • +
  • 这是一个数据包的样子的示例,一段电流的视觉表示,计算机可以把它转化为1和0的,这就是我们所知道的二进制,可以代表任何数字数据。
  • +
  • 这些小数据包通过路由器发送,并且如果一个文件是用一个信息包(发送)太大,它可以被分成帧(较小的小数据包)。帧发送到目的地不必采用相同的路由。
  • +
  • 他们可以决定哪个路由是开放的,取其速度最快,而且因为它们具有IP地址,所有的路由器知道从哪里发送。一旦他们到达终点目的地,计算机知道如何把所有的信息重新拼合到一起。
  • +
+

源代码,解释器和编译器

    +
  • 源代码本身是程序员创建的文本文档:他们键入它,它的字母,数字和符号。
  • +
  • 如果你把这个给别人,让他们看看在他们的电脑查看这个文档,这没法帮助他们查看电子邮件,它不是一个浏览器,它只是一个文本文档。
  • +
  • 计算机必须有一种解释它的东西,并使一些有用的东西可以运行于它。
  • +
  • 有两种主要的方法是这样做:无论是由一个解释器或编译器。
  • +
  • 每个浏览器都有一个解释器,这就是JavaScript如何被处理的。
  • +
  • 其他的语言,像C++,使用编译器。
  • +
  • 与解释器不同的是,编译器将其所有的工作都放在了程序员的端上。
  • +
  • 他们发送他们的包,他们的产品,它已经被编译,它已经可以在一台机器上运行。
  • +
  • 然而,JavaScript,和其他的解释型语言,您只需编写JavaScript,用户端的浏览器有能力解释它所以你不需要编译它。
  • +
+

硬件基础知识

硬件组成

计算机由4个基本部分组成:输入、输出、CPU(中央处理器)、存储器。

+
    +
  • 输入是你放入计算机的东西。

    +
  • +
  • 输出是你在显示屏上所看见的或在扬声器里所听见的。

    +
  • +
  • CPU代表中央处理单元,并且当我们提到计算机时都能想起它。CPU是实现功能,运行软件的部分,由CPU来操作数据。

    +
  • +
  • 存储器是我们存储数据和信息的地方。CPU对存储器具有独占访问权。你无法通过输入和输出来访问内存而不使用CPU。

    +
      +
    • 现在存储器可以分为短期存储器, 称作RAM, 或者是长期存储器.

      +
    • +
    • 长期存储器通常是硬盘, 但是也可以是使CD-ROM或者是闪存设备, 或是任何这一类的。

      +
    • +
    +
  • +
+

除了这四个基本部分, 我们今天还有另外三样东西要谈论: 主板,扩展槽和电源。

+
    +
  • 主板是连接这些硬件的东西。当这些数据到处流动试图找出该去哪时, 主板帮助他们导流他们,使他们去向正确的地方

    +
  • +
  • 扩展卡是声卡,显卡,这类可以提升用户体验的东西。

    +
  • +
  • 电源, 就像他的名字一样, 给我们的计算机提供电力。它通常是一个部件并有一个风扇在上面来帮助它散热。

    +
      +
    • 一个芯片全是由成千上万的晶体管(一种只能是0或1的开关)组成的
    • +
    +
  • +
  • 所有的这些晶体管塞进了一个芯片里,并且这就是芯片存储信息的方式。
      +
    • 在一个芯片上集成的晶体管数量决定了芯片的大小和速度
    • +
    +
  • +
  • 摩尔定律是观察到自从1965年芯片上的晶体管数量每两年增加一倍的一种规律。
      +
    • 二进制码是一种非常常见的计算机语言,它只能是1或0,也是on(开)或关,1代表on(开),0代表off(关)。
    • +
    +
  • +
+

数据

数据大小

+
    +
  • 最小的单位我们称之为1比特(bit)。比特(bit)只能是0或1, 也就是回到我们一直在学习的二进制。

    +
  • +
  • 字节, 很常见, 8比特(bit)。很多东西都可以用二个字节来表示。

    +
  • +
  • 下一步是KB, 1024个字节, 或者8192个比特(bit).

    +
  • +
  • 之后是MB, 1024个字节的2次方。

    +
  • +
  • 之后就是GB了, 1024个字节的3次方; TB, 1024个字节的4次方, 和PB, 1024个字节的5次方。

    +
  • +
+

数据的速率

+
    +
  • 数据速率不同于数据大小, 通常是计算每秒多少比特, 而大小是计算有多少比特。
  • +
  • 一旦我们涉及到指数级,数据速率的表示就有了很大的不同
  • +
  • 怎么讨论数据速率取决于我们在讨论的东西。

    +
      +
    • 在音频下载中,我们使用KB/s

      +
    • +
    • 网速,我们使用MB/s。如果你看到你的网速有多少多少比特每秒,记住它永远比按你提到数据大小时的字节小8倍。

      +
    • +
    • 网络中, 我们用GB/s (十亿比特每秒!)。

      +
    • +
    +
  • +
  • 这里主要选取方式是速度是按比特来计算而大小是按字节来计算。
  • +
+

超级计算机

    +
  • 一种使用一种叫做并行处理的技术同理用很多CPU处理同一问题的计算机。
  • +
+

服务器

    +
  • 服务器拥有并访问大量的数据或程序。
  • +
+

工作站

    +
  • 一种和个人电脑非常相似的计算机, 但是更耗能且贵的多。
  • +
+

微控制器

    +
  • 一种可能你汽车里都有的计算机,它非常擅长处理小型的特定的任务但是不可以像个人计算机那样操作和使用。

    +
  • +
  • 主板的构成是处理器和内存之间的桥梁-如果它不这样做,它就不是一个主板。但是大多数主板要比这个功能多的多。主要是它们有扩展槽和接口。

    +
      +
    • 扩展槽使你可以任意插入提高计算机性能的东西,而不需要让中央处理器负担更多。
    • +
    +
  • +
  • 举个例子,显卡和声卡可以提供更好的声音和更出色的显示效果从而显著提升用户体验,却不会拖慢电脑。
      +
    • 网卡也可以插进扩展槽。
    • +
    +
  • +
  • PC和扩展卡在笔记本上很常见,并且扩展卡因为他们尺寸很小被合并到了主板上。
      +
    • 在电脑上,你会知道有一个地方链接USB,电源接口,SD卡,以太网,甚至是一个音频插孔来通过耳机听声音。它们都是接口,主板上一个可以连接外源到CPU来获取或者给予信息的地方。
    • +
    +
  • +
+

数据网络

三种类型:局域网(LAN),广域网(WAN),虚拟专用网(VPN)。

+
    +
  • 局域网就像是一小组计算机连接在了一起。局域网最重要的是这些计算机离得很近。

    +
  • +
  • 广域网是两个,三个或者更多的局域网长距离的连接起来。

    +
      +
    • 你也许认为他们通过因特网(Internet)相连接,对于VPN来说(虚拟专用网,设计上和广域网相似),你是对的。

      +
    • +
    • 一个广域网通常租用来自因特网公司的电缆来创建连接。

      +
    • +
    +
  • +
  • 因特网(Internet)的第一部分:因特网是如何工作的。

    +
      +
    • IP地址:你可能已经习惯了每个设备都有它自己的IP地址,就像一个房子有它自己的地址一样。

      +
    • +
    • 如果一个设备没有IP地址因特网不能向它分发数据。

      +
    • +
    • 不止设备有,猫(modem)和路由器(router)也有,数据传输路上的每一步都有。

      +
    • +
    • IP地址由位置所决定,起始于5个大型国际地区。

      +
    • +
    • 从左到右,数字意味着你的位置。

      +
    • +
    +
  • +
+

Chrome调试学习

elements标签

    +
  • 在chrome浏览器中右击选中Inspect element即可访问elements标签,然后你就可以随便修改元素文本,元素标签和任何其他CSS或者HTML。

    +
  • +
  • 这些修改不会自动保存,不能当做IDE或者可以保存内容的编辑器。你可以使用chrome中的’persistent authoring’功能去保存更改。

    +
  • +
  • 记住这里层叠,继承和其他CSS规则都可以使用,另外,被覆盖的式样会以穿越文字的横线的形式展示。
  • +
  • 需要注意的是现在”树”中看到的代码是当前的HTML,而不是页面加载时的代码。如果你用JavaScript或Jquery来改变页面元素,”树”就会更新。
  • +
  • Padding,border和margin都很容易在右下角的彩色盒子里面检查和编辑。
  • +
+

network标签

    +
  • network标签页是用来回答’页面中哪个部分最耗时间’或’哪个调用初始化了网络请求’
  • +
  • network仪表盘记录了页面中每个元素加载的详细信息。
  • +
  • 每一个请求都记录在network仪表盘的底部日志中
  • +
  • 观察底部的线条,你会注意到彩色图案。每一个颜色都代表了请求中的不同类型内容。
  • +
  • 线越长代表网络耗时越大,我们最终目标就是缩短线长。如果出现长线条,说明某些内容拖慢了整个网页。
  • +
  • 点击请求日志,会看到更加详细的请求信息。
  • +
+

Sources标签

    +
  • Sources标签页对调试JavaScript帮助很大。项目越大,越难准确找到问题所在。
  • +
  • 可以对代码的不同部分设置断点,代码会到此停止执行。
  • +
  • 有很多种断点类型可以使用,如一行特定代码,一个DOM事件,XMLHTTP请求或一个JavaScript事件。
  • +
  • 设置好断电之后,浏览器在进入这段代码或事件时,会暂停执行。
  • +
  • 通过减缓代码执行,我们就有机会仔细观察每一个设置点,准确跟踪页面行为。
  • +
  • 一旦断点设置好,我们就可以逐步浏览和检查页面中断点处的代码。
  • +
  • 和elements标签一样,可以实时编辑代码观察结果,不过记得在别处保存更改。
  • +
+

Timeline 面板

    +
  • Timeline 面板可以在应用运行时记录和分析所有行为。此处最适合分析应用性能问题。
  • +
  • 就像通过network标签找出时间耗费,通过sources标签找出有问题的代码一样,通过Timeline可以观察到更多详细细节。
  • +
  • 使用点击timeline的圆形按钮,你可以记录(捕获)堆栈,js性能,内存和图形绘制(CSS)等信息。
  • +
  • chrome会以小粒度的详细日志来展现这些信息,可以通过很多种形式来查看。
  • +
  • 所有这些信息可以帮助你很好地理解浏览器中发生的行为,尤其是发现内存占用比较多的事件。
  • +
  • 在加载新页面之前记得先点击’clear’按钮再开始记录。
  • +
  • 当记录JS事件时,点击title或左侧的’function call’,会重定向到resource标签,同时定位到函数所在位置的代码行。
  • +
+

Profiles 面板

    +
  • Profiles 面板可以提供web应用或页面的执行时间和内存,主要是针对运行于页面或app上的JavaScript。
  • +
  • 这里可以收集到3种类型的概述信息: CPU profile,HEAP snapshot和HEAP profile。HEAP profiles更多的和内存使用信息相关,CPU profile和JavaScript性能相关。
  • +
  • V8分析器可以帮助定位JavaScript中的性能问题,有助于优化代码。
  • +
  • 每一个profile都可以在左侧查看,可以对每个页面采集多个profile。总体而言,profiles标签页非常适合优化代码。
  • +
+

Resources 面板

    +
  • Resources 面板可以显示已经加载的资源,包括:IndexedDB,Web SQL数据库,local storage,session storage,cookies,Application Cache, 图片, 字体和样式表。
  • +
  • 可以在浏览器中查看和修改所有这些信息。
  • +
  • 当你进行高级网站构建时,resources 面板可以帮你更好的理解app和页面的实时性要求。
  • +
+

Audit 工具

    +
  • Audit 工具帮助你逐步改善你的页面。
  • +
  • Audit 工具会自动给你提供改进建议。
  • +
+

Console 面板

    +
  • Console 面板提供了2个主要功能:在开发过程中记录调试信息和提供一个可以用于和文档、开发工具交互的shell环境。
  • +
  • 可以使用标准JS语法和特定控制台命令来查看原始数据和结构化数据。
  • +
  • 从API中获取的JSON数据是典型的结构化数据。
  • +
  • 信息经常会叠加满屏幕,你可以键入’clear()’来清空屏幕。通过勾选’Preserve Log’可以保存日志。
  • +
  • 有几种不同的日志命令,比如console.log()用于基本日志记录,console.error()和colsole.warn()用于一些重要信息。
  • +
  • Console中可以追踪异常(代码出现了问题),甚至可以在出现异常时暂停代码的执行,如果你还记得,这个功能在Source标签页中也有。
  • +
+

复杂度学习

    +
  • 时间复杂度是讨论算法花费多少时间的一种方式。它对于更快的提高精简中的软件的运行速度有着很大的作用。
  • +
  • 当你编写代码的时候,你应该要知道这个软件需要花多长时间去执行。没有人想要创造一个由于运行缓慢而让用户觉得沮丧的项目。
  • +
  • 时间复杂度相对于一个算法来说,是一个或多个函数的集合。
  • +
  • 大O符号专门帮助您识别是算法没有’规模’好,还是在有大量不同的用户,信息,或其他投入量工作下运行良好。
  • +
  • 这不符合摩尔定律 - 不管你的电脑有多大有快捷,如果算法是成倍地低效率,它在现实就无法使用。
  • +
  • 通过在算法中执行的基本操作(基本操作=一个花费固定时间执行的操作)的数目统计来测量时间复杂度。
  • +
  • 时间复杂度由函数T(n)表示。O代表函数,(n)表示作用于元件的数目。
  • +
  • 渐进时间复杂度,对于任何的有效输入它可能花费的最长时间,是表达时间复杂度最常见的方式。
  • +
  • 当你讨论大0符号,通常指的是最坏的情况。
  • +
  • 作为一个经验法则,任何用N ^ 2或其他指数对于多个用户的网站来说都不是好的算法。
  • +
+
O(1)——确定一个数字是奇数或偶数。O(1)是一个静态的时间常量,不管有多少信息或有多少用户它都是一样的不改变。
O(log N)——发现一个字在字典里(使用二分法检索)。二分法检索是一个典型的“分而治之”的算法。
O(N)——看一本书
O(N log N)——排序一副扑克牌(使用归并排序)
O(N ^ 2)——在你购物车上检查你的购物清单的每一样东西
O(∞)-掷硬币,直到它落在头上
+

计算机安全

针对密码的字典攻击

    +
  • 当创建您的密码,有些网站需要极其特殊和复杂的密码,这实际上是一个也不必要的。
  • +
  • 他们想要保护你不受字典攻击的攻击。
  • +
  • 字典攻击就是尝试字典里的每一个字词,或者是它自己数据库中的常见词汇和很多人使用过的密码
  • +
  • 大多数密码都没有这个简单的,但是,这并不重要。
  • +
  • 他们只需要简单的密码就可以攻击巨量的账户。
  • +
  • 在创建密码时,你想要使用不同的类型,数字和符号,但是最有效的方法之一是出现一些随机的字母。
  • +
+

网络钓鱼

    +
  • 网络钓鱼,是模仿其他正规站点的网页或者邮件,试图欺骗用户输入自己的个人信息,而它却没有连接到它所模仿的站点。
  • +
  • 一般情况下,两种方式来保护免受这些攻击:在地址栏中查看网址,打开一个新的浏览器并转到它所声称的网站。
  • +
  • 我们还要学习加密和HTTPS。
  • +
  • 如果你是在星巴克试图访问您的银行帐户,您有理由怀疑有人能看到,并采集您的信息。
  • +
  • 你会想在网址的开头寻找一个绿色的HTTPS而不是HTTP。
  • +
  • 这意味着,你向该网站所发送的密码和其他信息都被加密,只有他们可以根据一串码解开的数据。
  • +
  • 一般情况下,只要你显示的是私人或敏感信息,检查一下HTTPS。
  • +
  • 其他一些提示:重要账户之间不要使用相同的代码。
  • +
  • 如果您使用的网站被黑客侵入,密码再长也没用。
  • +
  • 同样,不要下载奇怪的文件。
  • +
  • 如果你下载的文件不是像.PDF,txt文件,JPG格式这样常见的文件类型,就要小心了。
  • +
  • 你下载的一些文件非常厉害,它们甚至可以在后台运行。
  • +
  • 最后,让你的软件更新,特别是联网的软件。
  • +
  • 信息泄露的一种方式就是’坏人’发现了旧版本的漏洞并突破了安全系统。
  • +
  • 这些漏洞在新版本中已经修复,如果你每个软件都保持更新,你可以避免很多问题。
  • +
+]]>
- - 数据库 - + web - - - - - MongoDB - - - -
- - - - - FreeCodeCamp学习笔记(二) - - /posts/e20ef482/ - -

FreeCodeCamp学习笔记(二)

基本概念

软件概念

  • 软件是程序或在硬件上运行的程序,写入硬件的代码,两种软件类型是操作系统和应用软件。
  • 有三个主要的操作系统:Windows,Mac和Linux。
  • 应用范围包括所有其他软件,如Web浏览器,游戏,还有像Photoshop,查看邮件,编辑文档的软件等。

CDN

  • 内容传递网络(CDN)是一种分布式服务器(网络),基于用户的地理位置向用户分发网页和其他Web内容,网页和内容分发服务器的起源。
  • CDN的目标是建立更高质量的网络连接。
  • CDNs通过为用户和用户目标站点之间建立快速通道或提供更快的建立在其他服务器上的镜像站点来达成目标。
  • 这个概念和这种类型的服务不是创新型的想法,但是它正使互联网更加普及。
  • 网站付费使用CDN服务,而CDN反过来you向因特网提供商付费来使用他们的服务和数据。
  • 谷歌托管库就是一种CDNs : developers.google.com/speed/libraries/#jquery
  • 谷歌托管那些(常用的)库,比起你自己(在自己的服务器上)部署这些库,你的用户就可以更快的访问到它。
  • 有可能的话,用户浏览器甚至会存储已经访问过的网站的缓存。

模拟与数字转换和压缩

  • 一个模拟声波可能看起来像任何东西,例子中它是一条波浪线。
  • 计算机采集和测量很多很多不同的点。把他们转化为数字,这就是所谓的采样。之后,计算机可以使用这些数字,并再次把它们变成声音。
  • 压缩的好处是,它是一个更小的文件:它更容易储存,它更容易发送给其他人,它只是占用更少的空间。
  • 压缩声音的一种常用方法是以更低的频率采样。
  • 另一种方式是,它从一个中点而不是0开始采样,所以所采集的数字更小。
  • 在图像中,它是通过测量一组16个的像素来压缩,而不是独立的。
  • 视频中减掉的部分是你想使用一个高质量的数字文件,但当你在压缩时,你需要决定压缩到何种程度以确保用户仍然有最好的体验。

联网

  • 路由器是连接不同的小范围网络的东西。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
我想打个比方:我是一名教师,我在一所学校工作。
假如说我有一个包,并且我需要把它送给我在民政事务处工作的人。
我不知道她在哪里,我不知道她的办公室所在地,但我知道她的名字。
我找我的秘书,像我的第一台路由器,我说"嘿,我需要找在民政事务处的某某,你能帮帮我吗?",她会说:"当然,我不知道她的办公室准确位置,但我知道,下一步,我可以找到她所在的区域。"
于是,她继续并将其它发送至到民政事务处的秘书,下一个路由器。
那秘书不知道我是谁或者我在哪里,但她看到包装上的名称,知道结束位置。
我想要去表达的是每个路由器只需要知道自己的小网,就在它旁边的站点。
它不必知道整个互联网,但只是它自己的连接。
它可以获取信息并说,好吧,我不知道确切位置这回事,但我会在正确的方向传递下去吧。
这就是它所需要做的事。
  • 路由器可以是不同的尺寸,不同容量,但他们做的是知道自己的邻居,获得信息,并传递向正确的方向。
  • 路由器甚至不必须有完整的包的信息。
  • 如果一台电脑正试图将信息发送到另一个时,数据可能会在不同的路由器之间分开,但是这没问题。计算机仍然知道如何正确地把信息重新组合到一起。
  • 所发送信息的小碎片被称为数据包。包实际上是一小段二进制代码。
  • 这是一个数据包的样子的示例,一段电流的视觉表示,计算机可以把它转化为1和0的,这就是我们所知道的二进制,可以代表任何数字数据。
  • 这些小数据包通过路由器发送,并且如果一个文件是用一个信息包(发送)太大,它可以被分成帧(较小的小数据包)。帧发送到目的地不必采用相同的路由。
  • 他们可以决定哪个路由是开放的,取其速度最快,而且因为它们具有IP地址,所有的路由器知道从哪里发送。一旦他们到达终点目的地,计算机知道如何把所有的信息重新拼合到一起。

源代码,解释器和编译器

  • 源代码本身是程序员创建的文本文档:他们键入它,它的字母,数字和符号。
  • 如果你把这个给别人,让他们看看在他们的电脑查看这个文档,这没法帮助他们查看电子邮件,它不是一个浏览器,它只是一个文本文档。
  • 计算机必须有一种解释它的东西,并使一些有用的东西可以运行于它。
  • 有两种主要的方法是这样做:无论是由一个解释器或编译器。
  • 每个浏览器都有一个解释器,这就是JavaScript如何被处理的。
  • 其他的语言,像C++,使用编译器。
  • 与解释器不同的是,编译器将其所有的工作都放在了程序员的端上。
  • 他们发送他们的包,他们的产品,它已经被编译,它已经可以在一台机器上运行。
  • 然而,JavaScript,和其他的解释型语言,您只需编写JavaScript,用户端的浏览器有能力解释它所以你不需要编译它。

硬件基础知识

硬件组成

计算机由4个基本部分组成:输入、输出、CPU(中央处理器)、存储器。

  • 输入是你放入计算机的东西。

  • 输出是你在显示屏上所看见的或在扬声器里所听见的。

  • CPU代表中央处理单元,并且当我们提到计算机时都能想起它。CPU是实现功能,运行软件的部分,由CPU来操作数据。

  • 存储器是我们存储数据和信息的地方。CPU对存储器具有独占访问权。你无法通过输入和输出来访问内存而不使用CPU。

    • 现在存储器可以分为短期存储器, 称作RAM, 或者是长期存储器.

    • 长期存储器通常是硬盘, 但是也可以是使CD-ROM或者是闪存设备, 或是任何这一类的。

除了这四个基本部分, 我们今天还有另外三样东西要谈论: 主板,扩展槽和电源。

  • 主板是连接这些硬件的东西。当这些数据到处流动试图找出该去哪时, 主板帮助他们导流他们,使他们去向正确的地方

  • 扩展卡是声卡,显卡,这类可以提升用户体验的东西。

  • 电源, 就像他的名字一样, 给我们的计算机提供电力。它通常是一个部件并有一个风扇在上面来帮助它散热。

    • 一个芯片全是由成千上万的晶体管(一种只能是0或1的开关)组成的
  • 所有的这些晶体管塞进了一个芯片里,并且这就是芯片存储信息的方式。
    • 在一个芯片上集成的晶体管数量决定了芯片的大小和速度
  • 摩尔定律是观察到自从1965年芯片上的晶体管数量每两年增加一倍的一种规律。
    • 二进制码是一种非常常见的计算机语言,它只能是1或0,也是on(开)或关,1代表on(开),0代表off(关)。

数据

数据大小

  • 最小的单位我们称之为1比特(bit)。比特(bit)只能是0或1, 也就是回到我们一直在学习的二进制。

  • 字节, 很常见, 8比特(bit)。很多东西都可以用二个字节来表示。

  • 下一步是KB, 1024个字节, 或者8192个比特(bit).

  • 之后是MB, 1024个字节的2次方。

  • 之后就是GB了, 1024个字节的3次方; TB, 1024个字节的4次方, 和PB, 1024个字节的5次方。

数据的速率

  • 数据速率不同于数据大小, 通常是计算每秒多少比特, 而大小是计算有多少比特。
  • 一旦我们涉及到指数级,数据速率的表示就有了很大的不同
  • 怎么讨论数据速率取决于我们在讨论的东西。

    • 在音频下载中,我们使用KB/s

    • 网速,我们使用MB/s。如果你看到你的网速有多少多少比特每秒,记住它永远比按你提到数据大小时的字节小8倍。

    • 网络中, 我们用GB/s (十亿比特每秒!)。

  • 这里主要选取方式是速度是按比特来计算而大小是按字节来计算。

超级计算机

  • 一种使用一种叫做并行处理的技术同理用很多CPU处理同一问题的计算机。

服务器

  • 服务器拥有并访问大量的数据或程序。

工作站

  • 一种和个人电脑非常相似的计算机, 但是更耗能且贵的多。

微控制器

  • 一种可能你汽车里都有的计算机,它非常擅长处理小型的特定的任务但是不可以像个人计算机那样操作和使用。

  • 主板的构成是处理器和内存之间的桥梁-如果它不这样做,它就不是一个主板。但是大多数主板要比这个功能多的多。主要是它们有扩展槽和接口。

    • 扩展槽使你可以任意插入提高计算机性能的东西,而不需要让中央处理器负担更多。
  • 举个例子,显卡和声卡可以提供更好的声音和更出色的显示效果从而显著提升用户体验,却不会拖慢电脑。
    • 网卡也可以插进扩展槽。
  • PC和扩展卡在笔记本上很常见,并且扩展卡因为他们尺寸很小被合并到了主板上。
    • 在电脑上,你会知道有一个地方链接USB,电源接口,SD卡,以太网,甚至是一个音频插孔来通过耳机听声音。它们都是接口,主板上一个可以连接外源到CPU来获取或者给予信息的地方。

数据网络

三种类型:局域网(LAN),广域网(WAN),虚拟专用网(VPN)。

  • 局域网就像是一小组计算机连接在了一起。局域网最重要的是这些计算机离得很近。

  • 广域网是两个,三个或者更多的局域网长距离的连接起来。

    • 你也许认为他们通过因特网(Internet)相连接,对于VPN来说(虚拟专用网,设计上和广域网相似),你是对的。

    • 一个广域网通常租用来自因特网公司的电缆来创建连接。

  • 因特网(Internet)的第一部分:因特网是如何工作的。

    • IP地址:你可能已经习惯了每个设备都有它自己的IP地址,就像一个房子有它自己的地址一样。

    • 如果一个设备没有IP地址因特网不能向它分发数据。

    • 不止设备有,猫(modem)和路由器(router)也有,数据传输路上的每一步都有。

    • IP地址由位置所决定,起始于5个大型国际地区。

    • 从左到右,数字意味着你的位置。

Chrome调试学习

elements标签

  • 在chrome浏览器中右击选中Inspect element即可访问elements标签,然后你就可以随便修改元素文本,元素标签和任何其他CSS或者HTML。

  • 这些修改不会自动保存,不能当做IDE或者可以保存内容的编辑器。你可以使用chrome中的’persistent authoring’功能去保存更改。

  • 记住这里层叠,继承和其他CSS规则都可以使用,另外,被覆盖的式样会以穿越文字的横线的形式展示。
  • 需要注意的是现在”树”中看到的代码是当前的HTML,而不是页面加载时的代码。如果你用JavaScript或Jquery来改变页面元素,”树”就会更新。
  • Padding,border和margin都很容易在右下角的彩色盒子里面检查和编辑。

network标签

  • network标签页是用来回答’页面中哪个部分最耗时间’或’哪个调用初始化了网络请求’
  • network仪表盘记录了页面中每个元素加载的详细信息。
  • 每一个请求都记录在network仪表盘的底部日志中
  • 观察底部的线条,你会注意到彩色图案。每一个颜色都代表了请求中的不同类型内容。
  • 线越长代表网络耗时越大,我们最终目标就是缩短线长。如果出现长线条,说明某些内容拖慢了整个网页。
  • 点击请求日志,会看到更加详细的请求信息。

Sources标签

  • Sources标签页对调试JavaScript帮助很大。项目越大,越难准确找到问题所在。
  • 可以对代码的不同部分设置断点,代码会到此停止执行。
  • 有很多种断点类型可以使用,如一行特定代码,一个DOM事件,XMLHTTP请求或一个JavaScript事件。
  • 设置好断电之后,浏览器在进入这段代码或事件时,会暂停执行。
  • 通过减缓代码执行,我们就有机会仔细观察每一个设置点,准确跟踪页面行为。
  • 一旦断点设置好,我们就可以逐步浏览和检查页面中断点处的代码。
  • 和elements标签一样,可以实时编辑代码观察结果,不过记得在别处保存更改。

Timeline 面板

  • Timeline 面板可以在应用运行时记录和分析所有行为。此处最适合分析应用性能问题。
  • 就像通过network标签找出时间耗费,通过sources标签找出有问题的代码一样,通过Timeline可以观察到更多详细细节。
  • 使用点击timeline的圆形按钮,你可以记录(捕获)堆栈,js性能,内存和图形绘制(CSS)等信息。
  • chrome会以小粒度的详细日志来展现这些信息,可以通过很多种形式来查看。
  • 所有这些信息可以帮助你很好地理解浏览器中发生的行为,尤其是发现内存占用比较多的事件。
  • 在加载新页面之前记得先点击’clear’按钮再开始记录。
  • 当记录JS事件时,点击title或左侧的’function call’,会重定向到resource标签,同时定位到函数所在位置的代码行。

Profiles 面板

  • Profiles 面板可以提供web应用或页面的执行时间和内存,主要是针对运行于页面或app上的JavaScript。
  • 这里可以收集到3种类型的概述信息: CPU profile,HEAP snapshot和HEAP profile。HEAP profiles更多的和内存使用信息相关,CPU profile和JavaScript性能相关。
  • V8分析器可以帮助定位JavaScript中的性能问题,有助于优化代码。
  • 每一个profile都可以在左侧查看,可以对每个页面采集多个profile。总体而言,profiles标签页非常适合优化代码。

Resources 面板

  • Resources 面板可以显示已经加载的资源,包括:IndexedDB,Web SQL数据库,local storage,session storage,cookies,Application Cache, 图片, 字体和样式表。
  • 可以在浏览器中查看和修改所有这些信息。
  • 当你进行高级网站构建时,resources 面板可以帮你更好的理解app和页面的实时性要求。

Audit 工具

  • Audit 工具帮助你逐步改善你的页面。
  • Audit 工具会自动给你提供改进建议。

Console 面板

  • Console 面板提供了2个主要功能:在开发过程中记录调试信息和提供一个可以用于和文档、开发工具交互的shell环境。
  • 可以使用标准JS语法和特定控制台命令来查看原始数据和结构化数据。
  • 从API中获取的JSON数据是典型的结构化数据。
  • 信息经常会叠加满屏幕,你可以键入’clear()’来清空屏幕。通过勾选’Preserve Log’可以保存日志。
  • 有几种不同的日志命令,比如console.log()用于基本日志记录,console.error()和colsole.warn()用于一些重要信息。
  • Console中可以追踪异常(代码出现了问题),甚至可以在出现异常时暂停代码的执行,如果你还记得,这个功能在Source标签页中也有。

复杂度学习

  • 时间复杂度是讨论算法花费多少时间的一种方式。它对于更快的提高精简中的软件的运行速度有着很大的作用。
  • 当你编写代码的时候,你应该要知道这个软件需要花多长时间去执行。没有人想要创造一个由于运行缓慢而让用户觉得沮丧的项目。
  • 时间复杂度相对于一个算法来说,是一个或多个函数的集合。
  • 大O符号专门帮助您识别是算法没有’规模’好,还是在有大量不同的用户,信息,或其他投入量工作下运行良好。
  • 这不符合摩尔定律 - 不管你的电脑有多大有快捷,如果算法是成倍地低效率,它在现实就无法使用。
  • 通过在算法中执行的基本操作(基本操作=一个花费固定时间执行的操作)的数目统计来测量时间复杂度。
  • 时间复杂度由函数T(n)表示。O代表函数,(n)表示作用于元件的数目。
  • 渐进时间复杂度,对于任何的有效输入它可能花费的最长时间,是表达时间复杂度最常见的方式。
  • 当你讨论大0符号,通常指的是最坏的情况。
  • 作为一个经验法则,任何用N ^ 2或其他指数对于多个用户的网站来说都不是好的算法。
1
2
3
4
5
6
7
8
9
10
11
O(1)——确定一个数字是奇数或偶数。O(1)是一个静态的时间常量,不管有多少信息或有多少用户它都是一样的不改变。
O(log N)——发现一个字在字典里(使用二分法检索)。二分法检索是一个典型的“分而治之”的算法。
O(N)——看一本书
O(N log N)——排序一副扑克牌(使用归并排序)
O(N ^ 2)——在你购物车上检查你的购物清单的每一样东西
O(∞)-掷硬币,直到它落在头上

计算机安全

针对密码的字典攻击

  • 当创建您的密码,有些网站需要极其特殊和复杂的密码,这实际上是一个也不必要的。
  • 他们想要保护你不受字典攻击的攻击。
  • 字典攻击就是尝试字典里的每一个字词,或者是它自己数据库中的常见词汇和很多人使用过的密码
  • 大多数密码都没有这个简单的,但是,这并不重要。
  • 他们只需要简单的密码就可以攻击巨量的账户。
  • 在创建密码时,你想要使用不同的类型,数字和符号,但是最有效的方法之一是出现一些随机的字母。

网络钓鱼

  • 网络钓鱼,是模仿其他正规站点的网页或者邮件,试图欺骗用户输入自己的个人信息,而它却没有连接到它所模仿的站点。
  • 一般情况下,两种方式来保护免受这些攻击:在地址栏中查看网址,打开一个新的浏览器并转到它所声称的网站。
  • 我们还要学习加密和HTTPS。
  • 如果你是在星巴克试图访问您的银行帐户,您有理由怀疑有人能看到,并采集您的信息。
  • 你会想在网址的开头寻找一个绿色的HTTPS而不是HTTP。
  • 这意味着,你向该网站所发送的密码和其他信息都被加密,只有他们可以根据一串码解开的数据。
  • 一般情况下,只要你显示的是私人或敏感信息,检查一下HTTPS。
  • 其他一些提示:重要账户之间不要使用相同的代码。
  • 如果您使用的网站被黑客侵入,密码再长也没用。
  • 同样,不要下载奇怪的文件。
  • 如果你下载的文件不是像.PDF,txt文件,JPG格式这样常见的文件类型,就要小心了。
  • 你下载的一些文件非常厉害,它们甚至可以在后台运行。
  • 最后,让你的软件更新,特别是联网的软件。
  • 信息泄露的一种方式就是’坏人’发现了旧版本的漏洞并突破了安全系统。
  • 这些漏洞在新版本中已经修复,如果你每个软件都保持更新,你可以避免很多问题。
]]>
- - + + FreeCodeCamp + 计算机基础知识 + +
+ + 数据结构与算法JavaScript学习(一) + /posts/742c7f0a/ +

数据结构与算法JavaScript学习(一)

数组

常用数组方法

    +
  • push方法,能把元素添加到数组的末尾

    +
  • +
  • unshift方法,可直接把数值插入到数组首位

    +
  • +
  • pop方法,删除数组里靠后的元素

    +
  • +
  • shift方法,删除数组的第一个元素

    +
  • +
  • splice方法,通过指定位置/索引,删除或增加相应位置和数量的元素

    +

    number.splice(5,3)删除从数组索引5开始3个元素

    +

    number.splice(5,0,2,3,4)从数组索引5开始增加3个元素2,3,4

    +
  • +
+ +

合并

    +
  • concat方法,合并数组,可迭代数组,把每个元素加入到最终数组
  • +
+

迭代器函数

    +
  • every方法,迭代数组中的每个元素,直到返回false
  • +
  • some方法,迭代数组中的每个元素,直到返回true
  • +
  • forEach方法,迭代整个数组
  • +
  • map方法,遍历数组,得到新数组
  • +
  • filter方法,遍历数组,返回新数组,返回的数组由使函数返回true的元素组成
  • +
  • reduce方法,接受一个函数作为参数,函数有四个参数:previousValue, currentValue, index, array.函数返回一个将被叠加到累加器的值,方法停止执行返回累加器
  • +
+

排序

    +
  • reverse方法,将数组元素反序输出
  • +
  • sort方法,排序,把元素默认成字符串进行相互比较
  • +
+

搜索

    +
  • indexOf方法,返回与参数匹配的第一个元素的索引
  • +
  • lastIndexOf方法,返回与参数匹配的最后一个元素的索引
  • +
+

输出字符串

    +
  • toString方法,把数组里所有元素输出为一个字符串
  • +
  • join方法,用不同分隔符把元素隔开
  • +
+

常用方法

    +
  • push(element(s)),添加一个或几个新元素到栈顶
  • +
  • pop(),移除栈顶的元素,同时返回被移除的元素
  • +
  • peek(),返回栈顶的元素,不对栈做修改
  • +
  • isEmpty(),看栈是否为空,空返回true,否则返回false
  • +
  • clear(),移除栈里的所有元素
  • +
  • size(),返回栈里元素的个数
  • +
+

完整实例

ES5实现:

+
function Stack() {
let items = [];
this.push = function(element){
items.push(element);
};
this.pop = function(){
return items.pop();
};
this.peek = function(){
return items[items.length-1];
};
this.isEmpty = function(){
return items.length == 0;
};
this.size = function(){
return items.length;
};
this.clear = function(){
items = [];
};
this.print = function(){
console.log(items.toString());
};
this.toString = function(){
return items.toString();
};
}
+

ES6语法:

+
class Stack {
constructor () {
this.items = [];
}
push(element){
this.items.push(element);
}
pop(){
return this.items.pop();
}
peek(){
return this.items[this.items.length-1];
}
isEmpty(){
return this.items.length == 0;
}
size(){
return this.items.length;
}
clear(){
this.items = [];
}
print(){
console.log(this.toString());
}
toString(){
return this.items.toString();
}
}
+

队列

常用方法

    +
  • enqueue(element(s)),向队列尾部添加一个或多个新的项
  • +
  • dequeue(),移除队列的第一项,并返回移除的元素
  • +
  • front(),返回队列第一个元素,不做任何修改
  • +
  • isEmpty(),判断是否为空,空返回true,否则返回false
  • +
  • size(),返回队列包含的元素个数
  • +
+

完整实例

ES5实现:

+
function Queue() {
let items = [];
this.enqueue = function(element){
items.push(element);
};
this.dequeue = function(){
return items.shift();
};
this.front = function(){
return items[0];
};
this.isEmpty = function(){
return items.length == 0;
};
this.clear = function(){
items = [];
};
this.size = function(){
return items.length;
};
this.print = function(){
console.log(items.toString());
};
}
+

ES6语法:

+
class Queue {
constructor () {
this.items = [];
}
enqueue(element){
this.items.push(element);
}
dequeue(){
return this.items.shift();
}
front(){
return this.items[0];
}
isEmpty(){
return this.items.length == 0;
}
size(){
return this.items.length;
}
clear(){
this.items = [];
}
print(){
console.log(this.toString());
}
toString(){
return this.items.toString();
}
}
+

排序算法

冒泡排序

function ArrayList(){
var array=[];
this.insert=function(item){
array.push(item);
};
this.toString=function(){
return array.join();
};
//交换两个数
var swap=function(index1,index2){
var aux=array[index1];
array[index1]=array[index2];
array[index2]=aux;
};
//改进冒泡排序
this.modifiedBubbleSort=function(){
var length=array.length;
for(var i=0;i<length;i++){//控制数组经过多少轮排序
for(var j=0;j<length-1-i;i++){//从第一位迭代至倒数第二位
if(array[j]>array[j+1]){//当前项和下一项比较
swap(j,j+1);
}
}
}
};
}
+

选择排序

function ArrayList(){
var array=[];
this.insert=function(item){
array.push(item);
};
this.toString=function(){
return array.join();
};
//交换两个数
var swap=function(index1,index2){
var aux=array[index1];
array[index1]=array[index2];
array[index2]=aux;
};
this.selectionSort=function(){
var length=array.length,indexMin;
for(var i=0;i<length-1;i++){//迭代数组
indexMin=i;//数组第一个为最小值
for(var j=i;j<length;j++){//从当前i至数组结束
if(array[indexMin]>array[j]){
indexMin=j;
}
}
if(i!==indexMin){
swap(i,indexMin);
}
}
};
}
+

插入排序

function ArrayList(){
var array=[];
this.insert=function(item){
array.push(item);
};
this.toString=function(){
return array.join();
};
this.insertionSort=function(){
var length=array.length,j,temp;
for (var i = 1; i < length; i++) {//迭代数组,默认第一项排序
j=i;//初始化一个辅助变量
temp=array[i];
while (j>0&&array[j-1]>temp) {//找到位置,前面的值比此值大
array[j]=array[j-1];//交换
j--;//j减少
}
array[j]=temp;//赋值
}
};
}
+

归并排序

function ArrayList(){
var array=[];
this.insert=function(item){
array.push(item);
};
this.toString=function(){
return array.join();
};
//归并排序:分治递归算法
this.mergeSort=function(){
array=mergeSortRec(array);
};
//将大数组分成小数组
var mergeSortRec=function (array) {
var length=array.length;
if (length===1) {
return array;
}
var mid=Math.floor(length/2),
left=array.slice(0,mmid),
right=array.slice(mid,length);
return merge(mergeSortRec(left),mergeSortRec(right));
};
//合并小数组
var merge=function(left,right){
var result=[],il=0,ir=0;
while (il<left.length && ir<right.length) {
if (left[il]<right[ir]) {
result.push(left[il++]);
}else {
result.push(right[ir++]);
}
}
while (il<left.length) {
result.push(left[il++]);
}
while (il<right.length) {
result.push(right[ir++]);
}
return result;
};
}
+

快速排序

function ArrayList(){
var array=[];
this.insert=function(item){
array.push(item);
};
this.toString=function(){
return array.join();
};
//快速排序:分治递归
this.quickSort=function () {
quick(array,0,array.length-1);
};
//快排
var quick=function (array,left,right) {
var index;
if (array.length>1) {
index=partition(array,left,right);
if (left<index-1) {
quick(array,left,index-1);
}
if (index<right) {
quick(array,index,right);
}
}
};
//划分过程
var partition=function(array,left,right){
var pivot=array[Math.floor((right+left)/2)],i=left,j=right;//选主元
while (i<=j) {
while (array[i]<pivot) {
i++;
}
while (array[j]>pivot) {
j--;
}
if (i<=j) {
swapQuickStort(array,i,j);
i++;
j--;
}
}
return i;
};
//交换数组元素
var swapQuickStort=function (array,index1,index2) {
var aux=array[index1];
array[index1]=array[index2];
array[index2]=aux;
};
}
+]]>
- - web - + web前端 - - - - - FreeCodeCamp - - 计算机基础知识 - - - -
- - - - - 数据结构与算法JavaScript学习(一) - - /posts/742c7f0a/ - -

数据结构与算法JavaScript学习(一)

数组

常用数组方法

  • push方法,能把元素添加到数组的末尾

  • unshift方法,可直接把数值插入到数组首位

  • pop方法,删除数组里靠后的元素

  • shift方法,删除数组的第一个元素

  • splice方法,通过指定位置/索引,删除或增加相应位置和数量的元素

    number.splice(5,3)删除从数组索引5开始3个元素

    number.splice(5,0,2,3,4)从数组索引5开始增加3个元素2,3,4

合并

  • concat方法,合并数组,可迭代数组,把每个元素加入到最终数组

迭代器函数

  • every方法,迭代数组中的每个元素,直到返回false
  • some方法,迭代数组中的每个元素,直到返回true
  • forEach方法,迭代整个数组
  • map方法,遍历数组,得到新数组
  • filter方法,遍历数组,返回新数组,返回的数组由使函数返回true的元素组成
  • reduce方法,接受一个函数作为参数,函数有四个参数:previousValue, currentValue, index, array.函数返回一个将被叠加到累加器的值,方法停止执行返回累加器

排序

  • reverse方法,将数组元素反序输出
  • sort方法,排序,把元素默认成字符串进行相互比较

搜索

  • indexOf方法,返回与参数匹配的第一个元素的索引
  • lastIndexOf方法,返回与参数匹配的最后一个元素的索引

输出字符串

  • toString方法,把数组里所有元素输出为一个字符串
  • join方法,用不同分隔符把元素隔开

常用方法

  • push(element(s)),添加一个或几个新元素到栈顶
  • pop(),移除栈顶的元素,同时返回被移除的元素
  • peek(),返回栈顶的元素,不对栈做修改
  • isEmpty(),看栈是否为空,空返回true,否则返回false
  • clear(),移除栈里的所有元素
  • size(),返回栈里元素的个数

完整实例

ES5实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function Stack() {
let items = [];
this.push = function(element){
items.push(element);
};
this.pop = function(){
return items.pop();
};
this.peek = function(){
return items[items.length-1];
};
this.isEmpty = function(){
return items.length == 0;
};
this.size = function(){
return items.length;
};
this.clear = function(){
items = [];
};
this.print = function(){
console.log(items.toString());
};
this.toString = function(){
return items.toString();
};
}

ES6语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Stack {
constructor () {
this.items = [];
}
push(element){
this.items.push(element);
}
pop(){
return this.items.pop();
}
peek(){
return this.items[this.items.length-1];
}
isEmpty(){
return this.items.length == 0;
}
size(){
return this.items.length;
}
clear(){
this.items = [];
}
print(){
console.log(this.toString());
}
toString(){
return this.items.toString();
}
}

队列

常用方法

  • enqueue(element(s)),向队列尾部添加一个或多个新的项
  • dequeue(),移除队列的第一项,并返回移除的元素
  • front(),返回队列第一个元素,不做任何修改
  • isEmpty(),判断是否为空,空返回true,否则返回false
  • size(),返回队列包含的元素个数

完整实例

ES5实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function Queue() {
let items = [];
this.enqueue = function(element){
items.push(element);
};
this.dequeue = function(){
return items.shift();
};
this.front = function(){
return items[0];
};
this.isEmpty = function(){
return items.length == 0;
};
this.clear = function(){
items = [];
};
this.size = function(){
return items.length;
};
this.print = function(){
console.log(items.toString());
};
}

ES6语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Queue {
constructor () {
this.items = [];
}
enqueue(element){
this.items.push(element);
}
dequeue(){
return this.items.shift();
}
front(){
return this.items[0];
}
isEmpty(){
return this.items.length == 0;
}
size(){
return this.items.length;
}
clear(){
this.items = [];
}
print(){
console.log(this.toString());
}
toString(){
return this.items.toString();
}
}

排序算法

冒泡排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function ArrayList(){
var array=[];
this.insert=function(item){
array.push(item);
};
this.toString=function(){
return array.join();
};
//交换两个数
var swap=function(index1,index2){
var aux=array[index1];
array[index1]=array[index2];
array[index2]=aux;
};
//改进冒泡排序
this.modifiedBubbleSort=function(){
var length=array.length;
for(var i=0;i<length;i++){//控制数组经过多少轮排序
for(var j=0;j<length-1-i;i++){//从第一位迭代至倒数第二位
if(array[j]>array[j+1]){//当前项和下一项比较
swap(j,j+1);
}
}
}
};
}

选择排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function ArrayList(){
var array=[];
this.insert=function(item){
array.push(item);
};
this.toString=function(){
return array.join();
};
//交换两个数
var swap=function(index1,index2){
var aux=array[index1];
array[index1]=array[index2];
array[index2]=aux;
};
this.selectionSort=function(){
var length=array.length,indexMin;
for(var i=0;i<length-1;i++){//迭代数组
indexMin=i;//数组第一个为最小值
for(var j=i;j<length;j++){//从当前i至数组结束
if(array[indexMin]>array[j]){
indexMin=j;
}
}
if(i!==indexMin){
swap(i,indexMin);
}
}
};
}

插入排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function ArrayList(){
var array=[];
this.insert=function(item){
array.push(item);
};
this.toString=function(){
return array.join();
};
this.insertionSort=function(){
var length=array.length,j,temp;
for (var i = 1; i < length; i++) {//迭代数组,默认第一项排序
j=i;//初始化一个辅助变量
temp=array[i];
while (j>0&&array[j-1]>temp) {//找到位置,前面的值比此值大
array[j]=array[j-1];//交换
j--;//j减少
}
array[j]=temp;//赋值
}
};
}

归并排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
function ArrayList(){
var array=[];
this.insert=function(item){
array.push(item);
};
this.toString=function(){
return array.join();
};
//归并排序:分治递归算法
this.mergeSort=function(){
array=mergeSortRec(array);
};
//将大数组分成小数组
var mergeSortRec=function (array) {
var length=array.length;
if (length===1) {
return array;
}
var mid=Math.floor(length/2),
left=array.slice(0,mmid),
right=array.slice(mid,length);
return merge(mergeSortRec(left),mergeSortRec(right));
};
//合并小数组
var merge=function(left,right){
var result=[],il=0,ir=0;
while (il<left.length && ir<right.length) {
if (left[il]<right[ir]) {
result.push(left[il++]);
}else {
result.push(right[ir++]);
}
}
while (il<left.length) {
result.push(left[il++]);
}
while (il<right.length) {
result.push(right[ir++]);
}
return result;
};
}

快速排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
function ArrayList(){
var array=[];
this.insert=function(item){
array.push(item);
};
this.toString=function(){
return array.join();
};
//快速排序:分治递归
this.quickSort=function () {
quick(array,0,array.length-1);
};
//快排
var quick=function (array,left,right) {
var index;
if (array.length>1) {
index=partition(array,left,right);
if (left<index-1) {
quick(array,left,index-1);
}
if (index<right) {
quick(array,index,right);
}
}
};
//划分过程
var partition=function(array,left,right){
var pivot=array[Math.floor((right+left)/2)],i=left,j=right;//选主元
while (i<=j) {
while (array[i]<pivot) {
i++;
}
while (array[j]>pivot) {
j--;
}
if (i<=j) {
swapQuickStort(array,i,j);
i++;
j--;
}
}
return i;
};
//交换数组元素
var swapQuickStort=function (array,index1,index2) {
var aux=array[index1];
array[index1]=array[index2];
array[index2]=aux;
};
}
]]>
- - + + JavaScript + +
+ + 使用JavaScript做一个AI五子棋 + /posts/d24e8921/ +

使用JavaScript做一个AI五子棋

实现步骤:

+
    +
  1. 搭建HTML、CSS、JS框架

    +
  2. +
  3. canvas画图

    +
  4. +
  5. js实现棋盘
  6. +
  7. js实现棋子
  8. +
  9. 棋盘落子
  10. +
+ +

canvas画图

<canvas id="chess" width="450px" height="450px"></canvas>
canvas {
display: block;
margin: 50px auto;
box-shadow: -2px -2px 2px #efefef, 5px 5px 5px #b9b9b9;
}
var chess = document.getElementById('chess');
var context = chess.getContext('2d');
+

js实现棋盘

var drawChessBoard = function() {
for (var i = 0; i < 15; i++) {
context.moveTo(15 + i * 30, 15);
context.lineTo(15 + i * 30, 435);
context.stroke();
context.moveTo(15, 15 + i * 30);
context.lineTo(435, 15 + i * 30);
context.stroke();
}
}
+

js实现棋子

var oneStep = function(i, j, me) {
//画圆
context.beginPath();
context.arc(15 + i * 30, 15 + j * 30, 13, 0, 2 * Math.PI);
context.closePath();
//渐变
var gradient = context.createRadialGradient(15 + i * 30 + 2, 15 + j * 30 - 2, 13, 15 + i * 30 + 2, 15 + j * 30 - 2, 0);
if (me) {
gradient.addColorStop(0, "#0a0a0a");
gradient.addColorStop(1, "#636766");
}else{
gradient.addColorStop(0, "#d1d1d1");
gradient.addColorStop(1, "#f9f9f9");
}
context.fillStyle = gradient;
context.fill();
}
+

落子

chess.onclick = function(e) {
var x = e.offsetX;
var y = e.offsetY;
//向下取整算出索引
var i = Math.floor(x / 30);
var j = Math.floor(y / 30);
if (chessBoard[i][j]==0) {
oneStep(i, j, me);
if (me) {
chessBoard[i][j]==1;
}else{
chessBoard[i][j]==2;
}
//me轮流取反
me = !me;
}
}
//默认黑子
var me = true;
//存储棋盘落子情况
var chessBoard=[];
for (var i = 0; i < 15; i++) {
chessBoard[i]=[];
for (var j = 0; i < 15; j++) {
chessBoard[i][j]=0;
}
}
+]]>
- - web前端 - + web前端 - - - - - JavaScript - - - -
- - - - - 使用JavaScript做一个AI五子棋 - - /posts/d24e8921/ - -

使用JavaScript做一个AI五子棋

实现步骤:

  1. 搭建HTML、CSS、JS框架

  2. canvas画图

  3. js实现棋盘
  4. js实现棋子
  5. 棋盘落子

canvas画图

1
2
3
4
5
6
7
8
9
10
<canvas id="chess" width="450px" height="450px"></canvas>
canvas {
display: block;
margin: 50px auto;
box-shadow: -2px -2px 2px #efefef, 5px 5px 5px #b9b9b9;
}
var chess = document.getElementById('chess');
var context = chess.getContext('2d');

js实现棋盘

1
2
3
4
5
6
7
8
9
10
var drawChessBoard = function() {
for (var i = 0; i < 15; i++) {
context.moveTo(15 + i * 30, 15);
context.lineTo(15 + i * 30, 435);
context.stroke();
context.moveTo(15, 15 + i * 30);
context.lineTo(435, 15 + i * 30);
context.stroke();
}
}

js实现棋子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var oneStep = function(i, j, me) {
//画圆
context.beginPath();
context.arc(15 + i * 30, 15 + j * 30, 13, 0, 2 * Math.PI);
context.closePath();
//渐变
var gradient = context.createRadialGradient(15 + i * 30 + 2, 15 + j * 30 - 2, 13, 15 + i * 30 + 2, 15 + j * 30 - 2, 0);
if (me) {
gradient.addColorStop(0, "#0a0a0a");
gradient.addColorStop(1, "#636766");
}else{
gradient.addColorStop(0, "#d1d1d1");
gradient.addColorStop(1, "#f9f9f9");
}
context.fillStyle = gradient;
context.fill();
}

落子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
chess.onclick = function(e) {
var x = e.offsetX;
var y = e.offsetY;
//向下取整算出索引
var i = Math.floor(x / 30);
var j = Math.floor(y / 30);
if (chessBoard[i][j]==0) {
oneStep(i, j, me);
if (me) {
chessBoard[i][j]==1;
}else{
chessBoard[i][j]==2;
}
//me轮流取反
me = !me;
}
}
//默认黑子
var me = true;
//存储棋盘落子情况
var chessBoard=[];
for (var i = 0; i < 15; i++) {
chessBoard[i]=[];
for (var j = 0; i < 15; j++) {
chessBoard[i][j]=0;
}
}
]]>
- - + + JavaScript + +
+ + HTML5存储初探 + /posts/bce46d0d/ +

HTML5存储初探

常见存储:

+
    +
  1. Cookies
  2. +
  3. localStorage && sessionStorage
  4. +
  5. indexedDB
  6. +
  7. application cache
  8. +
+

其它客户端存储:

+
    +
  1. userData

    +

    只有IE支持(IE5.0 … 9.0)

    +
  2. +
  3. google Gears

    +
      +
    • chrome (12.0后放弃支持)
    • +
    • 引擎:64SQLite
    • +
    • 需要用户授权
    • +
    +
  4. +
+ +

Cookies

Cookies是一种能够让网站服务器把少量数据储存到客户端的硬盘或内存,或是从客户端的硬盘读取数据的一种技术。Cookies是当你浏览某网站时,由Web服务器置于你硬盘上的一个非常小的文本文件,它可以记录你的用户ID、密码、浏览过的网页、停留的时间等信息。

+

当你再次来到该网站时,网站通过读取Cookies,得知你的相关信息,就可以做出相应的动作,如在页面显示欢迎你的标语,或者让你不用输入ID、密码就直接登录等等

+

Cookies文件是在无声无息中伴随浏览器进入我们本地硬盘的,当我们浏览某个站点时,该站点很可能将记录我们隐私的cookies文件上传到本地硬盘。

+

H5存储解决了cookie的问题

+
    +
  • 解决cookie总数和单个大小的限制(4k 4095B)
  • +
  • 解决请求头常带存储信息的问题
  • +
  • 解决关系型存储的问题
  • +
  • 跨浏览器
  • +
+

本地存储( localStorage && sessionStorage)

+

图片不经常更改,不过如果图片bash64比较大的话,会比较浪费资源)

+
+
    +
  • 常用属性和方法:

    +
    localStorage.key(i)
    .length
    .getItem("<key>")
    .setItem("<key>","<value>")
    .removeItem("<key>")
    .clear()
    +
  • +
  • 使用注意事项:

    +
      +
    • 使用前先判断浏览器是否支持(浏览器开启无痕模式后不能用,有的可读但不可写,所以不能用 if(window.localStorage){}来做兼容处理,先set,然后再捕获异常)
    • +
    • 写数据时,要异常处理,避免抛出容量错误
    • +
    • 避免将敏感信息写入localStorage
    • +
    • 注意key的唯一性,会被覆盖
    • +
    +
  • +
+
    +
  • 使用场景:
      +
    • 利用本地数据,减少网络传输
    • +
    • 弱网络环境下,高延迟,低带宽,尽量把数据本地化
    • +
    +
  • +
+
    +
  • H5本地存储的使用限制
      +
    • 需要添加存储更新策略和过期控制
    • +
    • 子域名之间不能共享存储数据
    • +
    • 超出存储后如何存储(LRU,FIFO) --> LRU (Least Recently Used) FIFO (先入先出)
    • +
    • server端如何取到数据(请求参数)
    • +
    +
  • +
+
    +
  • localStorage优点:
      +
    • 存储大小达5M
    • +
    • 兼容性好,功能强大
    • +
    • 应用范围广
    • +
    +
  • +
+

IndexedDB

    +
  • 定义

    +

    一种能在浏览器中持久存储结构化数据的数据库,并为web应用提供了丰富的查询能力。

    +
  • +
  • 浏览器支持

    +

    chromw11+,FF4+,IE10+,移动端支持弱

    +
  • +
  • 存储结构

    +

    按域名分配独立空间,一个域名下可创建多个数据库,一个DB可以创建多个对象储存空间(表),一个对象存储空间可以创建多个对象数据。

    +

    IndexedSQL

    +
  • +
  • 功能

    +
      +
    • 增删改
    • +
    • 事务
    • +
    • 游标
    • +
    • 索引
    • +
    +
  • +
+

注:w3c已不在维护Web SQL.

+

离线缓存(application cache)

    +
  • 离线缓存(application cache):让web应用在离线情况下继续使用,通过manifest文件指明要缓存的资源

    +
  • +
  • 检测是否在线:navigator.onLine

    +
  • +
  • 原理(如图):读取离线缓存,同时检查manifest文件,有更新时更新文件和缓存

    +

    H51

    +
  • +
  • appcache使用和更新

    +
      +
    • 使用:创建manifest文件
    • +
    • 修改资源文件,必须通过修改manifest文件来更新被缓存的文件列表
    • +
    +

    H52

    +
  • +
  • 优点

    +
      +
    • 完全离线
    • +
    • 资源被缓存,加载更快
    • +
    • 降低server负载
    • +
    +
  • +
+
    +
  • 缺陷
      +
    • 含有manifest属性的当前页一定会被缓存
    • +
    • 更新依赖manifest文件,更新后需要再次刷新
    • +
    • 更新是全局性的,无法单点更新
    • +
    • 对于链接的参数变化敏感,不同的参数视为不同的文件
    • +
    • 占用资源
    • +
    • 更新内容会在下次生效
    • +
    +
  • +
+
    +
  • 浏览器支持:IE8-不支持

    +
  • +
  • 适用场景

    +
      +
    • 单地址的页面(无参数)
    • +
    • 对实时性要求不高的业务
    • +
    • 离线webapp
    • +
    +
  • +
+

总结

    +
  • H5存储优势:

    +
      +
    • 存储空间大
    • +
    • 接口丰富
    • +
    • 数据相对安全
    • +
    • 关系型
    • +
    • 省流量
    • +
    +
  • +
  • H5存储劣势:

    +
      +
    • 浏览器兼容( localStorage 和 app cache 主流浏览器都兼容的不错 )
    • +
    • 同源策略( localStorage 不可以跨子域,manifest 所引用的文件必须在同一个域名下面 )
    • +
    • 脚本控制( 只能在浏览器端存放;服务器端想拿到数据,只能通过请求 )
    • +
    • 更新策略(不像cookie可以设置过期时间;比如localStorage永不过期,必须自己写一套更新机制 )
    • +
    +
  • +
+]]>
- - web前端 - + web前端 - - - - - JavaScript - - - -
- - - - - HTML5存储初探 - - /posts/bce46d0d/ - -

HTML5存储初探

常见存储:

  1. Cookies
  2. localStorage && sessionStorage
  3. indexedDB
  4. application cache

其它客户端存储:

  1. userData

    只有IE支持(IE5.0 … 9.0)

  2. google Gears

    • chrome (12.0后放弃支持)
    • 引擎:64SQLite
    • 需要用户授权

Cookies

Cookies是一种能够让网站服务器把少量数据储存到客户端的硬盘或内存,或是从客户端的硬盘读取数据的一种技术。Cookies是当你浏览某网站时,由Web服务器置于你硬盘上的一个非常小的文本文件,它可以记录你的用户ID、密码、浏览过的网页、停留的时间等信息。

当你再次来到该网站时,网站通过读取Cookies,得知你的相关信息,就可以做出相应的动作,如在页面显示欢迎你的标语,或者让你不用输入ID、密码就直接登录等等

Cookies文件是在无声无息中伴随浏览器进入我们本地硬盘的,当我们浏览某个站点时,该站点很可能将记录我们隐私的cookies文件上传到本地硬盘。

H5存储解决了cookie的问题

  • 解决cookie总数和单个大小的限制(4k 4095B)
  • 解决请求头常带存储信息的问题
  • 解决关系型存储的问题
  • 跨浏览器

本地存储( localStorage && sessionStorage)

图片不经常更改,不过如果图片bash64比较大的话,会比较浪费资源)

  • 常用属性和方法:

    1
    2
    3
    4
    5
    6
    localStorage.key(i)
    .length
    .getItem("<key>")
    .setItem("<key>","<value>")
    .removeItem("<key>")
    .clear()
  • 使用注意事项:

    • 使用前先判断浏览器是否支持(浏览器开启无痕模式后不能用,有的可读但不可写,所以不能用 if(window.localStorage){}来做兼容处理,先set,然后再捕获异常)
    • 写数据时,要异常处理,避免抛出容量错误
    • 避免将敏感信息写入localStorage
    • 注意key的唯一性,会被覆盖
  • 使用场景:
    • 利用本地数据,减少网络传输
    • 弱网络环境下,高延迟,低带宽,尽量把数据本地化
  • H5本地存储的使用限制
    • 需要添加存储更新策略和过期控制
    • 子域名之间不能共享存储数据
    • 超出存储后如何存储(LRU,FIFO) --> LRU (Least Recently Used) FIFO (先入先出)
    • server端如何取到数据(请求参数)
  • localStorage优点:
    • 存储大小达5M
    • 兼容性好,功能强大
    • 应用范围广

IndexedDB

  • 定义

    一种能在浏览器中持久存储结构化数据的数据库,并为web应用提供了丰富的查询能力。

  • 浏览器支持

    chromw11+,FF4+,IE10+,移动端支持弱

  • 存储结构

    按域名分配独立空间,一个域名下可创建多个数据库,一个DB可以创建多个对象储存空间(表),一个对象存储空间可以创建多个对象数据。

    IndexedSQL

  • 功能

    • 增删改
    • 事务
    • 游标
    • 索引

注:w3c已不在维护Web SQL.

离线缓存(application cache)

  • 离线缓存(application cache):让web应用在离线情况下继续使用,通过manifest文件指明要缓存的资源

  • 检测是否在线:navigator.onLine

  • 原理(如图):读取离线缓存,同时检查manifest文件,有更新时更新文件和缓存

    H51

  • appcache使用和更新

    • 使用:创建manifest文件
    • 修改资源文件,必须通过修改manifest文件来更新被缓存的文件列表

    H52

  • 优点

    • 完全离线
    • 资源被缓存,加载更快
    • 降低server负载
  • 缺陷
    • 含有manifest属性的当前页一定会被缓存
    • 更新依赖manifest文件,更新后需要再次刷新
    • 更新是全局性的,无法单点更新
    • 对于链接的参数变化敏感,不同的参数视为不同的文件
    • 占用资源
    • 更新内容会在下次生效
  • 浏览器支持:IE8-不支持

  • 适用场景

    • 单地址的页面(无参数)
    • 对实时性要求不高的业务
    • 离线webapp

总结

  • H5存储优势:

    • 存储空间大
    • 接口丰富
    • 数据相对安全
    • 关系型
    • 省流量
  • H5存储劣势:

    • 浏览器兼容( localStorage 和 app cache 主流浏览器都兼容的不错 )
    • 同源策略( localStorage 不可以跨子域,manifest 所引用的文件必须在同一个域名下面 )
    • 脚本控制( 只能在浏览器端存放;服务器端想拿到数据,只能通过请求 )
    • 更新策略(不像cookie可以设置过期时间;比如localStorage永不过期,必须自己写一套更新机制 )
]]>
- - + + HTML + +
+ + FreeCodeCamp学习笔记(一) + /posts/6bfb34d8/ +

FreeCodeCamp学习笔记(一)

HTML学习

    +
  • a标签用#做占位符

    +
  • +
  • img标签里应加alt属性,为了盲人朋友

    +
    <a href="#">
    <img class="smaller-image thick-green-border" alt="A cute orange cat lying on its back" src="/images/relaxing-cat.jpg">
    </a>
    +
  • +
  • input标签加placeholder做占位符提示,在需要设置必填项的时候加required属性

    +
    <input type="text" placeholder="cat photo URL" required>
    +
  • +
  • 单选和复选按钮应加入到label标签里,name属性名应一致,checked为默认选中

    +
    <label><input type="radio" name="indoor-outdoor" checked> Indoor</label>
    <label><input type="radio" name="indoor-outdoor"> Outdoor</label>
    <label><input type="checkbox" name="personality" checked> Loving</label>
    <label><input type="checkbox" name="personality"> Lazy</label>
    <label><input type="checkbox" name="personality"> Energetic</label>
    +
  • +
+ +

CSS学习

浏览器读取 CSS 的顺序是从上到下,这意味着,在发生冲突时,浏览器会使用最后的 CSS 声明。但是如果设置id, id 属性总是具有更高的优先级。

+

很多情况下,你会使用 CSS 库,这些库可能会意外覆盖掉你自己的 CSS。所以当你需要确保某元素具有指定的 CSS 时,你可以使用 !important.

+

盒子模型

有三个影响HTML元素布局的重要属性:padding(内边距)、margin(外边距)、border(边框)。

+
    +
  • 元素的 padding 控制元素内容 content和元素边框 border 之间的距离。

    +

    当加大 padding, 将扩大元素内容和元素边框的距离。

    +
  • +
  • 元素的外边距 margin 控制元素边框 border 和元素实际所占空间的距离。

    +

    当增大 margin 时,将会增加元素边框和元素实际所占空间之间的距离。

    +

    如果你将一个元素的 margin 设置为负值,元素将会变大。

    +
  • +
+

RGB颜色设置

0 是 hex code(十六进制编码)中最小的一个,它代表颜色的完全缺失。

+

F 是 hex code(十六进制编码)中最大的一个,它代表最大可能的亮度。

+

16 个值和 6 个位置意味着我们有 16 的 6 次方,或者说超过 1600 万种可能的颜色.

+

Hex code 遵循 red-green-blue(红-绿-蓝),或者叫 rgb 格式。hex code 中的前两位表示颜色中红色的数量,第三四位代表绿色的数量,第五六位代表蓝色的数量。

+

jQuery学习

jQuery通过选择器来选择一个元素的,然后操作元素做些改变。

+
    +
  1. 要让所有的按钮做弹回效果,只要把这段代码写在
    $(document).ready(function() {});
    +
  2. +
+

里面,然后

$("button").addClass("animated bounce");

+
    +
  1. 你可以通过jQuery的addClass()方法给元素添加class,也可以通过jQueryremoveClass()方法去掉元素上的class。

    +
    $("#target2").removeClass("btn-default");
    +
  2. +
  3. jQuery有一个叫做.css()的方法能让你改变元素的CSS样式。

    +
    $("#target1").css("color", "blue");
    +
  4. +
  5. jQuery有一个.prop()的方法让你来调整元素的属性

    +
    $("button").prop("disabled", true);
    +
  6. +
  7. jQuery的.html()方法可以添加HTML标签和文字到元素,而元素之前的内容都会被方法的内容所替换掉。

    +

    我们是通过em[emphasize]标签来重写和强调标题文本的:

    +
    $("h3").html("<em>jQuery Playground</em>");
    +
  8. +
  9. jQuery 还有一个类似的方法叫.text(),它只能改变文本但不能修改标记。换句话说,这个方法只会把传进来的任何东西(包括标记)当成文本来显示。

    +
  10. +
  11. jQuery有一个appendTo()方法可以把选中的元素加到其他元素中。

    +
    $("#target4").appendTo("#left-well");
    +
  12. +
  13. jQuery的clone()方法可以拷贝元素。
    方法链function chaining,使用起来很方便

    +
    $("#target2").clone().appendTo("#right-well");
    +
  14. +
  15. 每个HTML元素根据继承属性都有父parent元素,jQuery有一个方法叫parent(),它允许你访问指定元素的父元素

    +
    $("#left-well").parent().css("background-color", "blue")
    +
  16. +
  17. 许多HTML元素都有children(子元素),每个子元素都从父元素那里继承了一些属性jQuery有一个方法叫children(),它允许你访问指定元素的子元素。

    +
    $("#left-well").children().css("color", "blue")
    +
  18. +
  19. jQuery 用CSS选择器来选取元素,target:nth-child(n) CSS选择器允许你按照索引顺序(从1开始)选择目标元素的所有子元素。

    +
    $(".target:nth-child(3)").addClass("animated bounce");
    +
  20. +
  21. 获取class为target且索引为奇数的所有元素,并给他们添加class。

    +
    $(".target:odd").addClass("animated shake");
    +
  22. +
+

jQuery里的索引是从0开始的,也就是说::odd 选择第2、4、6个元素,因为target#2(索引为1),target#4(索引为3),target6(索引为5)。获取class为target且索引为偶数的所有元素,并给他们添加class。

$(".target:even").addClass("animated shake");

+
    +
  1. 让整个body都有淡出效果(fadeOut):

    +
    $("body").addClass("animated fadeOut");
    +
  2. +
  3. $(document).ready(),这个函数中的代码只会在我们的页面加载时候运行一次,确保执行js之前页面所有的dom已经准备就绪。

    +
  4. +
  5. 增加一个click事件,通过点击事件来更改文本。

    +
    $("#getMessage").on("click", function(){
    $(".message").html("Here is the message");
    });
    +
  6. +
+

JavaScript基础

循环

    +
  • 一个条件语句只能执行一次代码,而一个循环语句可以多次执行代码。

    +
  • +
  • JavaScript 中最常见的循环就是“for循环”。

    +
      +
    • for循环中的三个表达式用分号隔开:for ([初始化]; [条件判断]; [计数器])
    • +
    • 初始化语句只会在执行循环开始之前执行一次。它通常用于定义和设置你的循环变量。
    • +
    • 条件判断语句会在每一轮循环的开始执行,只要条件判断为 true 就会继续执行循环。当条件为 false的时候,循环将停止执行。这意味着,如果条件在一开始就为 false,这个循环将不会执行。
    • +
    • 计数器是在每一轮循环结束时执行,通常用于递增或递减。
    • +
    • for循环可以按照我们指定的顺序来迭代,通过更改我们的 计数器,我们可以按照偶数顺序来迭代。
    • +
    • for循环也可以逆向迭代,只要我们定义好合适的条件。
    • +
    • 迭代输出一个数组的每个元素是 JavaScript 中的常见需求, for 循环可以做到这一点。记住数组的索引从零开始的,这意味着数组的最后一个元素的下标是:数组的长度 - 1。
    • +
    • 如果你有一个二维数组,可以使用相同的逻辑,先遍历外面的数组,再遍历里面的子数组。对于内部循环,我们可以通过 arr[i] 的 .length 来获得子数组的长度,因为 arr[i] 的本身就是一个数组。
    • +
    +
  • +
  • 另一种类型的 JavaScript 循环被称为while循环,因为它规定,当(while)条件为真,循环才会执行,反之不执行。
  • +
+

Math

    +
  • Math.random()用来生成一个在0(包括0)到1(不包括1)之间的随机小数,因此Math.random()可能返回0但绝不会返回1。要生成的随机数是在两个指定的数之间。

    +
  • +
  • 用 Math.floor() 向下取整 获得它最近的整数

    +
    Math.floor(Math.random() * 20);
    +
  • +
  • 定义一个最小值和一个最大值。

    +
    Math.floor(Math.random() * (max - min + 1)) + min
    +
  • +
+

正则

    +
  • Regular expressions 正则表达式被用来根据某种匹配模式来寻找strings中的某些单词。
  • +
  • 我们可以把这个正则表达式分成几段:
      +
    • / 是这个正则表达式的头部
    • +
    • the 是我们想要匹配的模式
    • +
    • / 是这个正则表达式的尾部
    • +
    • g 代表着 global(全局),意味着返回所有的匹配而不仅仅是第一个。
    • +
    • i 代表着忽略大小写,意思是当我们寻找匹配的字符串的时候忽略掉字母的大小写。
    • +
    +
  • +
  • 我们可以在正则表达式中使用特殊选择器来选取特殊类型的值。
      +
    • 特殊选择器中的一种就是数字选择器\d,意思是被用来获取一个字符串的数字.在JavaScript中, 数字选择器类似于: /\d/g
    • +
    • 在选择器后面添加一个加号标记(+),例如:/\d+/g,它允许这个正则表达式匹配一个或更多数字。尾部的g是’global’的简写,意思是允许这个正则表达式 找到所有的匹配而不是仅仅找到第一个匹配。
    • +
    • 我们也可以使用正则表达式选择器 \s 来选择一个字符串中的空白。空白字符有" " (空格符)、\r (回车符)、\n (换行符)、\t (制表符) 和 \f (换页符)。空白正则表达式类似于:/\s+/g
    • +
    • 你可以用正则表达式选择器的大写版本 来转化任何匹配。举个例子:\s 匹配任何空白字符,\S 匹配任何非空白字符。
    • +
    +
  • +
+

JSON与API

    +
  • JavaScript Object Notation 简称 JSON,它使用JavaScript对象的格式来存储数据。JSON是灵活的,因为它允许数据结构是字符串,数字,布尔值,字符串,和对象的任意组合。

    +
  • +
  • 数组中有多个 JSON 对象的时候,对象与对象之间要用逗号隔开。

    +
  • +
  • 通过串联起来的点操作符或中括号操作符来访问JSON对象的嵌套属性。因为属性的名字带有空格,请使用中括号操作符来访问属性的值。

    +
  • +
  • JSON对象可以嵌套对象和数组。与访问嵌套对象一样,用中括号操作符同样可以访问嵌套数组。

    +
  • +
  • 函数返回的永远是整个对象

    +
  • +
  • 使用中括号操作符来访问对象的变量属性

    +
  • +
  • JSON是一种非常简洁的数据格式。它通常表现为了两种形式,一种为单个对象,一种为多个对象

    +
      +
    • 单个对象类似于:
    • +
    +
    {name:'盖伦',advantage:'单挑无敌'}
    +
      +
    • 多个对象类似于:
    • +
    +
    [{name:'盖伦',advantage:'单挑无敌'},{name:'诺克',advantage:'上单霸主'}]
    +
      +
    • 每个对象属性和属性值的组合就是我们经常听到的”键值对(key-value pairs)”。
    • +
    +
  • +
  • 当你需要根据服务器返回的数据来动态改变页面的时候,应用程序接口(API)就派上用场了。API——应用程序接口(Application Programming Interface)是计算机之间相互交流沟通的工具。

    +
  • +
  • 许多网站的应用程序接口(API)都是通过一种称为JSON格式的数据来传输的,JSON 是 JavaScript Object Notation的简写。

    +
  • +
+

举例:

+
    +
  • 从JSON API中获得了数据:

    +
    $.getJSON("/json/cats.json", function(json) {
    $(".message").html(JSON.stringify(json));
    });
    +
  • +
  • 把它们展现到我们的HTML页面中吧。

    +
      +
    • 使用.forEach()函数来循环遍历JSON数据写到html变量中。
    • +
    • 首先我们定义一个HTML变量,var html = "";
    • +
    • 然后,我们使用.forEach()函数来循环遍历JSON数据写到html变量中,最后把html变量显示到我们的页面中。
    • +
    +
    json.forEach(function(val) {
    var keys = Object.keys(val);
    html += "<div class = 'cat'>";
    keys.forEach(function(key) {
    html += "<b>" + key + "</b>: " + val[key] + "<br>";
    });
    html += "</div><br>";
    });
    +
  • +
  • 获得的JSON数组中,每个对象都包含了一个以imageLink为键(key),以猫的图片的url为值(value)的键值对。

    +

    遍历,用imageLink的属性来显示img元素的图片。

    +
    html += "<img src = '" + val.imageLink + "'>";
    +
  • +
  • 不想把所有从JSON API中得到的图片都展现出来,可以在遍历之前做一次过滤。把其中 “id” 键的值为1的图片过滤掉。

    +
    json = json.filter(function(val) {
    return (val.id !== 1);
    });
    +
  • +
  • 可以通过浏览器navigator获得我们当前所在的位置geolocation。位置的信息包括经度longitude和纬度latitude。

    +
    if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
    $("#data").html("latitude: " + position.coords.latitude + "<br>longitude: " + position.coords.longitude);
    });
    }
    +
  • +
+

Object对象

    +
  • 可以使用构造函数来创建对象。

    +
  • +
  • 构造函数通常使用大写字母开头,以便把自己和其他普通函数区别开。

    +

    下面便是一个构造函数:

    +
    var Car = function() {
    this.wheels = 4;
    this.engines = 1;
    this.seats = 1;
    };
    +
  • +
  • 在构造函数中,this 指向被此构造函数创建出来的对象 。所以当我们在构造函数中写:

    +
    this.wheels = 4;
    +
      +
    • 创建出来的新对象将带有 wheels 属性,并且赋值为 4.
    • +
    +
  • +
  • 构造函数描述了它所创建出来的对象。

    +
  • +
  • 使用构造函数时,我们通过在它前面使用 new 关键字 来对它进行调用,如下:

    +
    var myCar = new Car();
    +
      +
    • myCar 现在成为了 Car 的一个实例(instance),它被构造函数描述成下面的样子:
    • +
    +
    {
    wheels: 4,
    engines: 1,
    seats: 1
    }
    +
      +
    • 要使用 new 关键字去调用构造函数。因为只有这样,Javascript才知道这是要去构造一个新对象 ,并且把构造函数中的 this 指向这个新对象。
    • +
    • 当 myCar(即 Car 的一个 实例 )创建后,他可以像普通对象一样被使用,包括创建、访问、修改它的属性等,就像我们使用其他对象一样。
    • +
    +
  • +
  • 对象拥有自己的特征,称为属性,对象还有自己的函数,称为方法。

    +
  • +
  • 构造函数中,我们使用了 this 指向当前(将要被创建的)对象中的公有属性 。

    +
  • +
  • 我们也可以创建私有属性和私有方法,它们两个在对象外部是不可访问的。

    +
  • +
+]]>
- - web前端 - + web前端 - - - - - HTML - - - -
- - - - - FreeCodeCamp学习笔记(一) - - /posts/6bfb34d8/ - -

FreeCodeCamp学习笔记(一)

HTML学习

  • a标签用#做占位符

  • img标签里应加alt属性,为了盲人朋友

    1
    2
    3
    <a href="#">
    <img class="smaller-image thick-green-border" alt="A cute orange cat lying on its back" src="/images/relaxing-cat.jpg">
    </a>
  • input标签加placeholder做占位符提示,在需要设置必填项的时候加required属性

    1
    <input type="text" placeholder="cat photo URL" required>
  • 单选和复选按钮应加入到label标签里,name属性名应一致,checked为默认选中

    1
    2
    3
    4
    5
    <label><input type="radio" name="indoor-outdoor" checked> Indoor</label>
    <label><input type="radio" name="indoor-outdoor"> Outdoor</label>
    <label><input type="checkbox" name="personality" checked> Loving</label>
    <label><input type="checkbox" name="personality"> Lazy</label>
    <label><input type="checkbox" name="personality"> Energetic</label>

CSS学习

浏览器读取 CSS 的顺序是从上到下,这意味着,在发生冲突时,浏览器会使用最后的 CSS 声明。但是如果设置id, id 属性总是具有更高的优先级。

很多情况下,你会使用 CSS 库,这些库可能会意外覆盖掉你自己的 CSS。所以当你需要确保某元素具有指定的 CSS 时,你可以使用 !important.

盒子模型

有三个影响HTML元素布局的重要属性:padding(内边距)、margin(外边距)、border(边框)。

  • 元素的 padding 控制元素内容 content和元素边框 border 之间的距离。

    当加大 padding, 将扩大元素内容和元素边框的距离。

  • 元素的外边距 margin 控制元素边框 border 和元素实际所占空间的距离。

    当增大 margin 时,将会增加元素边框和元素实际所占空间之间的距离。

    如果你将一个元素的 margin 设置为负值,元素将会变大。

RGB颜色设置

0 是 hex code(十六进制编码)中最小的一个,它代表颜色的完全缺失。

F 是 hex code(十六进制编码)中最大的一个,它代表最大可能的亮度。

16 个值和 6 个位置意味着我们有 16 的 6 次方,或者说超过 1600 万种可能的颜色.

Hex code 遵循 red-green-blue(红-绿-蓝),或者叫 rgb 格式。hex code 中的前两位表示颜色中红色的数量,第三四位代表绿色的数量,第五六位代表蓝色的数量。

jQuery学习

jQuery通过选择器来选择一个元素的,然后操作元素做些改变。

  1. 要让所有的按钮做弹回效果,只要把这段代码写在
    1
    $(document).ready(function() {});

里面,然后

1
$("button").addClass("animated bounce");

  1. 你可以通过jQuery的addClass()方法给元素添加class,也可以通过jQueryremoveClass()方法去掉元素上的class。

    1
    $("#target2").removeClass("btn-default");
  2. jQuery有一个叫做.css()的方法能让你改变元素的CSS样式。

    1
    $("#target1").css("color", "blue");
  3. jQuery有一个.prop()的方法让你来调整元素的属性

    1
    $("button").prop("disabled", true);
  4. jQuery的.html()方法可以添加HTML标签和文字到元素,而元素之前的内容都会被方法的内容所替换掉。

    我们是通过em[emphasize]标签来重写和强调标题文本的:

    1
    $("h3").html("<em>jQuery Playground</em>");
  5. jQuery 还有一个类似的方法叫.text(),它只能改变文本但不能修改标记。换句话说,这个方法只会把传进来的任何东西(包括标记)当成文本来显示。

  6. jQuery有一个appendTo()方法可以把选中的元素加到其他元素中。

    1
    $("#target4").appendTo("#left-well");
  7. jQuery的clone()方法可以拷贝元素。
    方法链function chaining,使用起来很方便

    1
    $("#target2").clone().appendTo("#right-well");
  8. 每个HTML元素根据继承属性都有父parent元素,jQuery有一个方法叫parent(),它允许你访问指定元素的父元素

    1
    $("#left-well").parent().css("background-color", "blue")
  9. 许多HTML元素都有children(子元素),每个子元素都从父元素那里继承了一些属性jQuery有一个方法叫children(),它允许你访问指定元素的子元素。

    1
    $("#left-well").children().css("color", "blue")
  10. jQuery 用CSS选择器来选取元素,target:nth-child(n) CSS选择器允许你按照索引顺序(从1开始)选择目标元素的所有子元素。

    1
    $(".target:nth-child(3)").addClass("animated bounce");
  11. 获取class为target且索引为奇数的所有元素,并给他们添加class。

    1
    $(".target:odd").addClass("animated shake");

jQuery里的索引是从0开始的,也就是说::odd 选择第2、4、6个元素,因为target#2(索引为1),target#4(索引为3),target6(索引为5)。获取class为target且索引为偶数的所有元素,并给他们添加class。

1
$(".target:even").addClass("animated shake");

  1. 让整个body都有淡出效果(fadeOut):

    1
    $("body").addClass("animated fadeOut");
  2. $(document).ready(),这个函数中的代码只会在我们的页面加载时候运行一次,确保执行js之前页面所有的dom已经准备就绪。

  3. 增加一个click事件,通过点击事件来更改文本。

    1
    2
    3
    $("#getMessage").on("click", function(){
    $(".message").html("Here is the message");
    });

JavaScript基础

循环

  • 一个条件语句只能执行一次代码,而一个循环语句可以多次执行代码。

  • JavaScript 中最常见的循环就是“for循环”。

    • for循环中的三个表达式用分号隔开:for ([初始化]; [条件判断]; [计数器])
    • 初始化语句只会在执行循环开始之前执行一次。它通常用于定义和设置你的循环变量。
    • 条件判断语句会在每一轮循环的开始执行,只要条件判断为 true 就会继续执行循环。当条件为 false的时候,循环将停止执行。这意味着,如果条件在一开始就为 false,这个循环将不会执行。
    • 计数器是在每一轮循环结束时执行,通常用于递增或递减。
    • for循环可以按照我们指定的顺序来迭代,通过更改我们的 计数器,我们可以按照偶数顺序来迭代。
    • for循环也可以逆向迭代,只要我们定义好合适的条件。
    • 迭代输出一个数组的每个元素是 JavaScript 中的常见需求, for 循环可以做到这一点。记住数组的索引从零开始的,这意味着数组的最后一个元素的下标是:数组的长度 - 1。
    • 如果你有一个二维数组,可以使用相同的逻辑,先遍历外面的数组,再遍历里面的子数组。对于内部循环,我们可以通过 arr[i] 的 .length 来获得子数组的长度,因为 arr[i] 的本身就是一个数组。
  • 另一种类型的 JavaScript 循环被称为while循环,因为它规定,当(while)条件为真,循环才会执行,反之不执行。

Math

  • Math.random()用来生成一个在0(包括0)到1(不包括1)之间的随机小数,因此Math.random()可能返回0但绝不会返回1。要生成的随机数是在两个指定的数之间。

  • 用 Math.floor() 向下取整 获得它最近的整数

    1
    Math.floor(Math.random() * 20);
  • 定义一个最小值和一个最大值。

    1
    Math.floor(Math.random() * (max - min + 1)) + min

正则

  • Regular expressions 正则表达式被用来根据某种匹配模式来寻找strings中的某些单词。
  • 我们可以把这个正则表达式分成几段:
    • / 是这个正则表达式的头部
    • the 是我们想要匹配的模式
    • / 是这个正则表达式的尾部
    • g 代表着 global(全局),意味着返回所有的匹配而不仅仅是第一个。
    • i 代表着忽略大小写,意思是当我们寻找匹配的字符串的时候忽略掉字母的大小写。
  • 我们可以在正则表达式中使用特殊选择器来选取特殊类型的值。
    • 特殊选择器中的一种就是数字选择器\d,意思是被用来获取一个字符串的数字.在JavaScript中, 数字选择器类似于: /\d/g
    • 在选择器后面添加一个加号标记(+),例如:/\d+/g,它允许这个正则表达式匹配一个或更多数字。尾部的g是’global’的简写,意思是允许这个正则表达式 找到所有的匹配而不是仅仅找到第一个匹配。
    • 我们也可以使用正则表达式选择器 \s 来选择一个字符串中的空白。空白字符有" " (空格符)、\r (回车符)、\n (换行符)、\t (制表符) 和 \f (换页符)。空白正则表达式类似于:/\s+/g
    • 你可以用正则表达式选择器的大写版本 来转化任何匹配。举个例子:\s 匹配任何空白字符,\S 匹配任何非空白字符。

JSON与API

  • JavaScript Object Notation 简称 JSON,它使用JavaScript对象的格式来存储数据。JSON是灵活的,因为它允许数据结构是字符串,数字,布尔值,字符串,和对象的任意组合。

  • 数组中有多个 JSON 对象的时候,对象与对象之间要用逗号隔开。

  • 通过串联起来的点操作符或中括号操作符来访问JSON对象的嵌套属性。因为属性的名字带有空格,请使用中括号操作符来访问属性的值。

  • JSON对象可以嵌套对象和数组。与访问嵌套对象一样,用中括号操作符同样可以访问嵌套数组。

  • 函数返回的永远是整个对象

  • 使用中括号操作符来访问对象的变量属性

  • JSON是一种非常简洁的数据格式。它通常表现为了两种形式,一种为单个对象,一种为多个对象

    • 单个对象类似于:
    1
    {name:'盖伦',advantage:'单挑无敌'}
    • 多个对象类似于:
    1
    [{name:'盖伦',advantage:'单挑无敌'},{name:'诺克',advantage:'上单霸主'}]
    • 每个对象属性和属性值的组合就是我们经常听到的”键值对(key-value pairs)”。
  • 当你需要根据服务器返回的数据来动态改变页面的时候,应用程序接口(API)就派上用场了。API——应用程序接口(Application Programming Interface)是计算机之间相互交流沟通的工具。

  • 许多网站的应用程序接口(API)都是通过一种称为JSON格式的数据来传输的,JSON 是 JavaScript Object Notation的简写。

举例:

  • 从JSON API中获得了数据:

    1
    2
    3
    $.getJSON("/json/cats.json", function(json) {
    $(".message").html(JSON.stringify(json));
    });
  • 把它们展现到我们的HTML页面中吧。

    • 使用.forEach()函数来循环遍历JSON数据写到html变量中。
    • 首先我们定义一个HTML变量,var html = "";
    • 然后,我们使用.forEach()函数来循环遍历JSON数据写到html变量中,最后把html变量显示到我们的页面中。
    1
    2
    3
    4
    5
    6
    7
    8
    json.forEach(function(val) {
    var keys = Object.keys(val);
    html += "<div class = 'cat'>";
    keys.forEach(function(key) {
    html += "<b>" + key + "</b>: " + val[key] + "<br>";
    });
    html += "</div><br>";
    });
  • 获得的JSON数组中,每个对象都包含了一个以imageLink为键(key),以猫的图片的url为值(value)的键值对。

    遍历,用imageLink的属性来显示img元素的图片。

    1
    html += "<img src = '" + val.imageLink + "'>";
  • 不想把所有从JSON API中得到的图片都展现出来,可以在遍历之前做一次过滤。把其中 “id” 键的值为1的图片过滤掉。

    1
    2
    3
    json = json.filter(function(val) {
    return (val.id !== 1);
    });
  • 可以通过浏览器navigator获得我们当前所在的位置geolocation。位置的信息包括经度longitude和纬度latitude。

    1
    2
    3
    4
    5
    if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
    $("#data").html("latitude: " + position.coords.latitude + "<br>longitude: " + position.coords.longitude);
    });
    }

Object对象

  • 可以使用构造函数来创建对象。

  • 构造函数通常使用大写字母开头,以便把自己和其他普通函数区别开。

    下面便是一个构造函数:

    1
    2
    3
    4
    5
    var Car = function() {
    this.wheels = 4;
    this.engines = 1;
    this.seats = 1;
    };
  • 在构造函数中,this 指向被此构造函数创建出来的对象 。所以当我们在构造函数中写:

    1
    this.wheels = 4;
    • 创建出来的新对象将带有 wheels 属性,并且赋值为 4.
  • 构造函数描述了它所创建出来的对象。

  • 使用构造函数时,我们通过在它前面使用 new 关键字 来对它进行调用,如下:

    1
    var myCar = new Car();
    • myCar 现在成为了 Car 的一个实例(instance),它被构造函数描述成下面的样子:
    1
    2
    3
    4
    5
    {
    wheels: 4,
    engines: 1,
    seats: 1
    }
    • 要使用 new 关键字去调用构造函数。因为只有这样,Javascript才知道这是要去构造一个新对象 ,并且把构造函数中的 this 指向这个新对象。
    • 当 myCar(即 Car 的一个 实例 )创建后,他可以像普通对象一样被使用,包括创建、访问、修改它的属性等,就像我们使用其他对象一样。
  • 对象拥有自己的特征,称为属性,对象还有自己的函数,称为方法。

  • 构造函数中,我们使用了 this 指向当前(将要被创建的)对象中的公有属性 。

  • 我们也可以创建私有属性和私有方法,它们两个在对象外部是不可访问的。

]]>
- - + + CSS + HTML + JavaScript + FreeCodeCamp + +
+ + CSS3实现3D魔方 + /posts/4370e84d/ +

CSS3实现3D魔方

实现思路

+
    +
  • 写出基础HTML框架

    +
  • +
  • 基本CSS样式,初始化

    +
  • +
  • CSS实现魔方的各个面:外轮廓和内盒子

    +
  • +
  • CSS3实现魔方表面的3D位置

    +
  • +
  • CSS3实现旋转

    +
  • +
+ +

第一步:HTML结构

六个面类似如下结构

+
<h1>3D魔方</h1>
<div class="view">
<div class="box">
<div class="red-surfaces">
<div id="one"></div>
<div id="two"></div>
<div id="three"></div>
<div id="four"></div>
<div id="five"></div>
<div id="six"></div>
<div id="seven"></div>
<div id="eight"></div>
<div id="nine"></div>
</div>
</div>
</div>
+

第二步:CSS初始化

* {
margin: 0px;
padding: 0px;
}
body {
min-height: 600px;
height: 100%
}
body h1 {
margin-top: 50px;
text-align: center;
}
.view {
margin: -60px auto;
width: 800px;
height: 800px;
position: relative;
border-radius: 20px;
-webkit-transform: scale(0.7);
}
+

第三步:CSS实现魔方的各个面-外轮廓和内盒子

外轮廓样式

+
.red-surfaces,
.blue-surfaces,
.green-surfaces,
.white-surfaces,
.orange-surfaces,
.yellow-surfaces {
height: 330px;
width: 330px;
position: absolute;
border-radius: 5px;
top: 235px;
left: 235px;
}
+

内盒子样式

+
.red-surfaces>div,
.blue-surfaces>div,
.green-surfaces>div,
.white-surfaces>div,
.orange-surfaces>div,
.yellow-surfaces>div {
height: 100px;
width: 100px;
display: inline-block;
border: 5px solid rgba(170, 170, 170, 0.9);
position: absolute;
}
+

内盒子颜色 : 六面

+
.red-surfaces>div {
background-color: rgba(255, 0, 0, 0.8);
}
+

内盒子定位 :九个小块

+
#one {
left: 0px;
top: 0px;
}
+

第四步:CSS3实现魔方表面的3D位置

六个表面不同角度设置

+
.red-surfaces {
-webkit-transform: rotateX(-90deg) translateZ(165px);
}
+

第五步:CSS3实现旋转

keyframe定义 :animation

+
    +
  • name规定需要绑定到选择器的keyframe名称
  • +
  • duration规定完成动画所花费的时间,以秒或毫秒计
  • +
  • timing-function规定动画的速度曲线
  • +
  • delay规定在动画开始之前的延迟
  • +
  • iteration-count规定动画应该播放的次数
  • +
  • direction规定是否应该轮流反向播放动画
  • +
+
.box{
-webkit-animation:BoxRotate 3s ease-in-out infinite;
}
+

动画旋转基准 : transform-origin

+
.box{
-webkit-transform-origin: 400px 400px 200px;
}
+

3D实现:transform-style

+
.box{
-webkit-transform-style: preserve-3d;
}
+

keyframe定义旋转

+
@-webkit-keyframes BoxRotate {
16% {
-webkit-transform: rotateY(-90deg) rotateZ(135deg);
}
33% {
-webkit-transform: rotateY(-90deg) rotateX(135deg);
}
50% {
-webkit-transform: rotateY(225deg) rotateZ(135deg);
}
66% {
-webkit-transform: rotateY(135deg) rotateX(135deg);
}
83% {
-webkit-transform: rotateX(135deg);
}
}
+

总结

CSS3也可以实现js实现的动画,而且还减少资源消耗,要熟练掌握新特性。

+]]>
- - web前端 - + web前端 - - - - - CSS - - HTML - - JavaScript - - FreeCodeCamp - - - -
- - - - - CSS3实现3D魔方 - - /posts/4370e84d/ - -

CSS3实现3D魔方

实现思路

  • 写出基础HTML框架

  • 基本CSS样式,初始化

  • CSS实现魔方的各个面:外轮廓和内盒子

  • CSS3实现魔方表面的3D位置

  • CSS3实现旋转

第一步:HTML结构

六个面类似如下结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<h1>3D魔方</h1>
<div class="view">
<div class="box">
<div class="red-surfaces">
<div id="one"></div>
<div id="two"></div>
<div id="three"></div>
<div id="four"></div>
<div id="five"></div>
<div id="six"></div>
<div id="seven"></div>
<div id="eight"></div>
<div id="nine"></div>
</div>
</div>
</div>

第二步:CSS初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
* {
margin: 0px;
padding: 0px;
}
body {
min-height: 600px;
height: 100%
}
body h1 {
margin-top: 50px;
text-align: center;
}
.view {
margin: -60px auto;
width: 800px;
height: 800px;
position: relative;
border-radius: 20px;
-webkit-transform: scale(0.7);
}

第三步:CSS实现魔方的各个面-外轮廓和内盒子

外轮廓样式

1
2
3
4
5
6
7
8
9
10
11
12
13
.red-surfaces,
.blue-surfaces,
.green-surfaces,
.white-surfaces,
.orange-surfaces,
.yellow-surfaces {
height: 330px;
width: 330px;
position: absolute;
border-radius: 5px;
top: 235px;
left: 235px;
}

内盒子样式

1
2
3
4
5
6
7
8
9
10
11
12
.red-surfaces>div,
.blue-surfaces>div,
.green-surfaces>div,
.white-surfaces>div,
.orange-surfaces>div,
.yellow-surfaces>div {
height: 100px;
width: 100px;
display: inline-block;
border: 5px solid rgba(170, 170, 170, 0.9);
position: absolute;
}

内盒子颜色 : 六面

1
2
3
.red-surfaces>div {
background-color: rgba(255, 0, 0, 0.8);
}

内盒子定位 :九个小块

1
2
3
4
#one {
left: 0px;
top: 0px;
}

第四步:CSS3实现魔方表面的3D位置

六个表面不同角度设置

1
2
3
.red-surfaces {
-webkit-transform: rotateX(-90deg) translateZ(165px);
}

第五步:CSS3实现旋转

keyframe定义 :animation

  • name规定需要绑定到选择器的keyframe名称
  • duration规定完成动画所花费的时间,以秒或毫秒计
  • timing-function规定动画的速度曲线
  • delay规定在动画开始之前的延迟
  • iteration-count规定动画应该播放的次数
  • direction规定是否应该轮流反向播放动画
1
2
3
.box{
-webkit-animation:BoxRotate 3s ease-in-out infinite;
}

动画旋转基准 : transform-origin

1
2
3
.box{
-webkit-transform-origin: 400px 400px 200px;
}

3D实现:transform-style

1
2
3
.box{
-webkit-transform-style: preserve-3d;
}

keyframe定义旋转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@-webkit-keyframes BoxRotate {
16% {
-webkit-transform: rotateY(-90deg) rotateZ(135deg);
}
33% {
-webkit-transform: rotateY(-90deg) rotateX(135deg);
}
50% {
-webkit-transform: rotateY(225deg) rotateZ(135deg);
}
66% {
-webkit-transform: rotateY(135deg) rotateX(135deg);
}
83% {
-webkit-transform: rotateX(135deg);
}
}

总结

CSS3也可以实现js实现的动画,而且还减少资源消耗,要熟练掌握新特性。

]]>
- - + + CSS + +
+ + kali linux 安装指南 + /posts/c1c013be/ +

kali linux 安装指南

+

Kali Linux是基于Debian的Linux发行版, 设计用于数字取证和渗透测试。Kali Linux预装了许多渗透测试软件,包括nmap (端口扫描器)、Wireshark (数据包分析器)、John the Ripper (密码破解器),以及Aircrack-ng (一应用于对无线局域网进行渗透测试的软件).用户可通过硬盘、live CD或live USB运行Kali Linux。Metasploit的Metasploit Framework支持Kali Linux,Metasploit一套针对远程主机进行开发和执行Exploit代码的工具。
Kali Linux既有32位和64位的镜像。可用于x86 指令集。同时还有基于ARM架构的镜像,可用于树莓派和三星的ARM Chromebook. –[百度百科]

+
+ +

安装步骤

下载

kali linux 官网

+

U盘刻录

镜像刻录U盘工具:Win32 Disk Imager

+

这个工具刻录的镜像比较完整,可直接用U盘启动,比软碟通要好。

+

安装

    +
  • 刻录U盘后重启电脑,不需要用EasyBCD。

    +
  • +
  • 重启电脑后进入bios,选择U盘启动

    +
  • +
  • 进入镜像,选择Graphical install选项,当然选择install也是一样的

    +
  • +
  • 安装语言、地区、键盘

    +
  • +
  • 无法挂载光盘解决:拔下U盘再插上,选择是继续

    +
  • +
  • 网络设备固件缺失:直接选择否继续

    +
  • +
  • 设置主机名和密码:默认用户名:root 密码:toor

    +
  • +
  • 磁盘分区(最重要一部分),这一部分是很重要的一步,一定要注意看清,选对,再操作。

    +
      +
    • 选择手动
    • +
    • 选择我们准备好要安装kali的那个分区
    • +
    • 分配分区:

      +
        +
      • /boot:启动分区
      • +
      • / :根分区
      • +
      • /home:用户目录
      • +
      • /tmp:临时文件
      • +
      • /usr:文件系统
      • +
      • /var:可变数据目录
      • +
      • /opt:附加应用程序
      • +
      • swap:交换分区
      • +
      +

      一般分/boot、/、/home、swap

      +

      分区方案关键点:

      +

      大数据库一般要加大/usr挂载点

      +

      多用户、下载类、多存储文件等要加大/home挂载点

      +

      文件小,用户多要注意/tmp/var挂载点大小

      +
    • +
    • 选择“分区设定结束并将修改写入磁盘”继续
    • +
    +
  • +
  • 开始格式化并写入磁盘,这个过程可能有点长,请耐心等待

    +
  • +
  • 网络镜像

    +
  • +
  • 写入引导(很重要一步):一定选是,是个坑

    +
  • +
  • 安装完成

    +
  • +
+

安装之后

    +
  • 更新软件源

    +

    修改sources.list文件:/etc/apt/sources.list

    +

    然后选择添加适合自己较快的源(可自由选择)

    +

    保存之后:

    +

    apt-get update #刷新系统

    +

    apt-get dist-upgrade #安装更新

    +
  • +
  • kali-linux安装中文输入法

    +

    apt-get install fcitx-table-wbpy ttf-wqy-microhei ttf-wqy-zenhei #拼音五笔

    +
  • +
  • 安装gnome管理软件

    +

    apt-get install gnome-tweak-tool

    +
  • +
  • 安装新立德

    +

    apt-get install synaptic

    +
  • +
  • 安装解压缩软件

    +

    apt-get install file-roller

    +
  • +
  • 安装smplayer视频播放器

    +

    apt-get install smplayer

    +
  • +
  • 安装多窗口终端

    +

    apt-get install terminator

    +
  • +
  • 安装VMware和VirtualBox

    +
  • +
+

使用及相关系统

渗透测试笔记:使用渗透工具进行测试

+

BackBox:黑客工具箱

+

Parrot Security os:本人用的最炫的一个系统,安装也简便,工具很强大,但是系统内部文件跟常规系统不太一样,适合对linux熟悉的人员使用

+

Cyborg Hawk:工具最多的一个系统,但是全英文,不支持中文,对英语水平要求很高。

+]]>
- - web前端 - + Linux - - - - - CSS - - - -
- - - - - kali linux 安装指南 - - /posts/c1c013be/ - -

kali linux 安装指南

Kali Linux是基于Debian的Linux发行版, 设计用于数字取证和渗透测试。Kali Linux预装了许多渗透测试软件,包括nmap (端口扫描器)、Wireshark (数据包分析器)、John the Ripper (密码破解器),以及Aircrack-ng (一应用于对无线局域网进行渗透测试的软件).用户可通过硬盘、live CD或live USB运行Kali Linux。Metasploit的Metasploit Framework支持Kali Linux,Metasploit一套针对远程主机进行开发和执行Exploit代码的工具。
Kali Linux既有32位和64位的镜像。可用于x86 指令集。同时还有基于ARM架构的镜像,可用于树莓派和三星的ARM Chromebook. –[百度百科]

安装步骤

下载

kali linux 官网

U盘刻录

镜像刻录U盘工具:Win32 Disk Imager

这个工具刻录的镜像比较完整,可直接用U盘启动,比软碟通要好。

安装

  • 刻录U盘后重启电脑,不需要用EasyBCD。

  • 重启电脑后进入bios,选择U盘启动

  • 进入镜像,选择Graphical install选项,当然选择install也是一样的

  • 安装语言、地区、键盘

  • 无法挂载光盘解决:拔下U盘再插上,选择是继续

  • 网络设备固件缺失:直接选择否继续

  • 设置主机名和密码:默认用户名:root 密码:toor

  • 磁盘分区(最重要一部分),这一部分是很重要的一步,一定要注意看清,选对,再操作。

    • 选择手动
    • 选择我们准备好要安装kali的那个分区
    • 分配分区:

      • /boot:启动分区
      • / :根分区
      • /home:用户目录
      • /tmp:临时文件
      • /usr:文件系统
      • /var:可变数据目录
      • /opt:附加应用程序
      • swap:交换分区

      一般分/boot、/、/home、swap

      分区方案关键点:

      大数据库一般要加大/usr挂载点

      多用户、下载类、多存储文件等要加大/home挂载点

      文件小,用户多要注意/tmp/var挂载点大小

    • 选择“分区设定结束并将修改写入磁盘”继续
  • 开始格式化并写入磁盘,这个过程可能有点长,请耐心等待

  • 网络镜像

  • 写入引导(很重要一步):一定选是,是个坑

  • 安装完成

安装之后

  • 更新软件源

    修改sources.list文件:/etc/apt/sources.list

    然后选择添加适合自己较快的源(可自由选择)

    保存之后:

    apt-get update #刷新系统

    apt-get dist-upgrade #安装更新

  • kali-linux安装中文输入法

    apt-get install fcitx-table-wbpy ttf-wqy-microhei ttf-wqy-zenhei #拼音五笔

  • 安装gnome管理软件

    apt-get install gnome-tweak-tool

  • 安装新立德

    apt-get install synaptic

  • 安装解压缩软件

    apt-get install file-roller

  • 安装smplayer视频播放器

    apt-get install smplayer

  • 安装多窗口终端

    apt-get install terminator

  • 安装VMware和VirtualBox

使用及相关系统

渗透测试笔记:使用渗透工具进行测试

BackBox:黑客工具箱

Parrot Security os:本人用的最炫的一个系统,安装也简便,工具很强大,但是系统内部文件跟常规系统不太一样,适合对linux熟悉的人员使用

Cyborg Hawk:工具最多的一个系统,但是全英文,不支持中文,对英语水平要求很高。

]]>
- - + + kali + Linux + +
+ + Google Hack + /posts/bb07c3a7/ +

Google Hack

+

这些命令在Google搜索引擎中才能使用

+
+

中文引号“ ”

在搜索关键字时,加上中文的“ ”号,你就能精确的只搜“ ”里面的文字了。

+

在搜索词后面加上“site:网站名”

举个例子:就如搜索 白帽 site:sina.com,那么就能搜索在新浪(sina.com)这个域名下的,有关“白帽”的信息了。
搜索出的结果均为新浪网中,与白帽有关的网页

+ +

“-”

就一个减号,在输入搜索词的后面,空格后加上一个减号。在减号后面输入你想过滤的东西,比如你想搜姚明,但又不想看他与篮球有关的东西,那么你只需要这样姚明 -篮球进行搜索就可以得出姚明与篮球无关的信息了。

+

* 号

在搜索词前面加上该符号,就可以搜索出与*号后面相关的词语的内容,如你输入*伟,那么出来的结果都会是XX伟,而不会是伟XX的内容。

+

filetype

爱在网上找资料的人都有很难找到想要的东西,要么名字对格式不对,要么格式对,内容不对。这里的filetype就可以准确的搜索出某个关键字下,你想要的文件名。如搜索数学 filetype:pdf,就会出来与数学有关的所有pdf文件。

+

info:url

在搜索栏中输入这个,就会出来被搜索网址的所有信息。

+

intitle:标题

在搜索词前输入这个命令,那么就会搜出网页中是以搜索词为标题的网页。

+

inurl:网址

输入网址后,是在搜索的结果中,把包含了URL的结果页面返回(也就是在结果中找有多少是你的网址的内容),如:inurl:baidu.com site:www.sina.com,则会搜索出新浪网中所有包含了baidu.com 网址的网页。

+

这个是独立使用的,输入这个之后,可以搜索出所有与这个网页有关联的网页。也就是我们平时进入网页后,可以在网页底部看到的合作网站。通过这个命令,我们可以不用进入网站就可以查出这个网站与那些网站合作了,明里暗里的都能看到哦。

+

location:区域

这个命令是为了精确区域而设计的,如你只想查深圳的女子大学的网页,那么就可以这样进行查找:女子大学 location:ShenZhen这样就会出来深圳区域所有的女子大学相关网页了,而不会把其它地区的女子大学的也搞过来。

+]]>
- - Linux - + web - - - - - kali - - Linux - - - -
- - - - - Google Hack - - /posts/bb07c3a7/ - -

Google Hack

这些命令在Google搜索引擎中才能使用

中文引号“ ”

在搜索关键字时,加上中文的“ ”号,你就能精确的只搜“ ”里面的文字了。

在搜索词后面加上“site:网站名”

举个例子:就如搜索 白帽 site:sina.com,那么就能搜索在新浪(sina.com)这个域名下的,有关“白帽”的信息了。
搜索出的结果均为新浪网中,与白帽有关的网页

“-”

就一个减号,在输入搜索词的后面,空格后加上一个减号。在减号后面输入你想过滤的东西,比如你想搜姚明,但又不想看他与篮球有关的东西,那么你只需要这样姚明 -篮球进行搜索就可以得出姚明与篮球无关的信息了。

* 号

在搜索词前面加上该符号,就可以搜索出与*号后面相关的词语的内容,如你输入*伟,那么出来的结果都会是XX伟,而不会是伟XX的内容。

filetype

爱在网上找资料的人都有很难找到想要的东西,要么名字对格式不对,要么格式对,内容不对。这里的filetype就可以准确的搜索出某个关键字下,你想要的文件名。如搜索数学 filetype:pdf,就会出来与数学有关的所有pdf文件。

info:url

在搜索栏中输入这个,就会出来被搜索网址的所有信息。

intitle:标题

在搜索词前输入这个命令,那么就会搜出网页中是以搜索词为标题的网页。

inurl:网址

输入网址后,是在搜索的结果中,把包含了URL的结果页面返回(也就是在结果中找有多少是你的网址的内容),如:inurl:baidu.com site:www.sina.com,则会搜索出新浪网中所有包含了baidu.com 网址的网页。

这个是独立使用的,输入这个之后,可以搜索出所有与这个网页有关联的网页。也就是我们平时进入网页后,可以在网页底部看到的合作网站。通过这个命令,我们可以不用进入网站就可以查出这个网站与那些网站合作了,明里暗里的都能看到哦。

location:区域

这个命令是为了精确区域而设计的,如你只想查深圳的女子大学的网页,那么就可以这样进行查找:女子大学 location:ShenZhen这样就会出来深圳区域所有的女子大学相关网页了,而不会把其它地区的女子大学的也搞过来。

]]>
- - + + 搜索技巧 + +
+ + CSS学习笔记 + /posts/948e1c93/ +

CSS学习笔记

CSS Positioning(定位)

CSS定位属性允许你为一个元素定位。它也可以将一个元素放在另一个元素后面,并指定一个元素的内容太大时,应该发生什么。元素可以使用的顶部,底部,左侧和右侧属性定位。然而,这些属性无法工作,除非是先设定position属性。他们也有不同的工作方式,这取决于定位方法

+ +

Static 定位

HTML元素的默认值,即没有定位,元素出现在正常的流中。

+

静态定位的元素不会受到top, bottom, left, right影响。

+

Fixed 定位

元素的位置相对于浏览器窗口是固定位置,即使窗口是滚动的它也不会移动。

+

Fixed定位使元素的位置与文档流无关,因此不占据空间。

+

Fixed定位的元素和其他元素重叠。

+

Relative 定位

相对定位元素的定位是相对其正常位置。

+

可以移动的相对定位元素的内容和相互重叠的元素,它原本所占的空间不会改变。相对定位元素经常被用来作为绝对定位元素的容器块。

+

Absolute 定位

绝对定位的元素的位置相对于最近的已定位父元素,如果元素没有已定位的父元素,那么它的位置相对于<html>

+

Absolutely定位使元素的位置与文档流无关,因此不占据空间。

+

Absolutely定位的元素和其他元素重叠。

+

重叠的元素

元素的定位与文档流无关,所以它们可以覆盖页面上的其它元素。

+

z-index属性指定了一个元素的堆叠顺序(哪个元素应该放在前面,或后面),一个元素可以有正数或负数的堆叠顺序。

+

CSS Float(浮动)

CSS 的Float(浮动),会使元素向左或向右移动,其周围的元素也会重新排列。
Float(浮动),往往是用于图像,但它在布局时一样非常有用。

+

元素怎样浮动

元素的水平方向浮动,意味着元素只能左右移动而不能上下移动。

+

一个浮动元素会尽量向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止。

+

浮动元素之后的元素将围绕它。

+

浮动元素之前的元素将不会受到影响。

+

清除浮动 - 使用 clear

元素浮动之后,周围的元素会重新排列,为了避免这种情况,使用 clear 属性。
clear 属性指定元素两侧不能出现浮动元素。

+

常见CSS布局

双飞翼布局

+

圣杯布局

+

流式布局

+

CSS3 模块

CSS3被拆分为”模块”。旧规范已拆分成小块,还增加了新的。

+

一些最重要CSS3模块如下:

+
    +
  • 选择器
  • +
  • 盒模型
  • +
  • 背景和边框
  • +
  • 文字特效
  • +
  • 2D/3D转换
  • +
  • 动画
  • +
  • 多列布局
  • +
  • 用户界面
  • +
+]]>
- - web - + web前端 - - - - - 搜索技巧 - - - -
- - - - - CSS学习笔记 - - /posts/948e1c93/ - -

CSS学习笔记

CSS Positioning(定位)

CSS定位属性允许你为一个元素定位。它也可以将一个元素放在另一个元素后面,并指定一个元素的内容太大时,应该发生什么。元素可以使用的顶部,底部,左侧和右侧属性定位。然而,这些属性无法工作,除非是先设定position属性。他们也有不同的工作方式,这取决于定位方法

Static 定位

HTML元素的默认值,即没有定位,元素出现在正常的流中。

静态定位的元素不会受到top, bottom, left, right影响。

Fixed 定位

元素的位置相对于浏览器窗口是固定位置,即使窗口是滚动的它也不会移动。

Fixed定位使元素的位置与文档流无关,因此不占据空间。

Fixed定位的元素和其他元素重叠。

Relative 定位

相对定位元素的定位是相对其正常位置。

可以移动的相对定位元素的内容和相互重叠的元素,它原本所占的空间不会改变。相对定位元素经常被用来作为绝对定位元素的容器块。

Absolute 定位

绝对定位的元素的位置相对于最近的已定位父元素,如果元素没有已定位的父元素,那么它的位置相对于<html>

Absolutely定位使元素的位置与文档流无关,因此不占据空间。

Absolutely定位的元素和其他元素重叠。

重叠的元素

元素的定位与文档流无关,所以它们可以覆盖页面上的其它元素。

z-index属性指定了一个元素的堆叠顺序(哪个元素应该放在前面,或后面),一个元素可以有正数或负数的堆叠顺序。

CSS Float(浮动)

CSS 的Float(浮动),会使元素向左或向右移动,其周围的元素也会重新排列。
Float(浮动),往往是用于图像,但它在布局时一样非常有用。

元素怎样浮动

元素的水平方向浮动,意味着元素只能左右移动而不能上下移动。

一个浮动元素会尽量向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止。

浮动元素之后的元素将围绕它。

浮动元素之前的元素将不会受到影响。

清除浮动 - 使用 clear

元素浮动之后,周围的元素会重新排列,为了避免这种情况,使用 clear 属性。
clear 属性指定元素两侧不能出现浮动元素。

常见CSS布局

双飞翼布局

圣杯布局

流式布局

CSS3 模块

CSS3被拆分为”模块”。旧规范已拆分成小块,还增加了新的。

一些最重要CSS3模块如下:

  • 选择器
  • 盒模型
  • 背景和边框
  • 文字特效
  • 2D/3D转换
  • 动画
  • 多列布局
  • 用户界面
]]>
- - + + CSS + +
+ + HTML学习笔记 + /posts/13b6b7c2/ +

HTML学习笔记

HTML结构及常用元素

<!DOCTYPE html>
<html>
<head>
<title>文档标题</title>
</head>
<body>
可见文本...
</body>
</html>
+ +
<h1>最大的标题</h1>
<h2> . . . </h2>
<h3> . . . </h3>
<h4> . . . </h4>
<h5> . . . </h5>
<h6>最小的标题</h6>
+
<p>这是一个段落。</p>
<br> (换行)
<hr> (水平线)
<!-- 这是注释 -->
<b>粗体文本</b>
<code>计算机代码</code>
<em>强调文本</em>
<i>斜体文本</i>
<kbd>键盘输入</kbd>
<pre>预格式化文本</pre>
<small>更小的文本</small>
<strong>重要的文本</strong>
<abbr> (缩写)
<address> (联系信息)
<bdo> (文字方向)
<blockquote> (从另一个源引用的部分)
<cite> (工作的名称)
<del> (删除的文本)
<ins> (插入的文本)
<sub> (下标文本)
<sup> (上标文本)
普通的链接:<a href="http://www.example.com/">链接文本</a>
图像链接: <a href="http://www.example.com/"><img src="URL" alt="替换文本"></a>
邮件链接: <a href="mailto:webmaster@example.com">发送e-mail</a>
书签:
<a id="tips">提示部分</a>
<a href="#tips">跳到提示部分</a>
<img src="URL" alt="替换文本" height="42" width="42">
+

HTML实例代码

<div>文档中的块级元素</div>
<span>文档中的内联元素</span>
+
<ul>
<li>项目</li>
<li>项目</li>
</ul>
+
<ol>
<li>第一项</li>
<li>第二项</li>
</ol>
+
<table border="1">
<tr>
<th>表格标题</th>
<th>表格标题</th>
</tr>
<tr>
<td>表格数据</td>
<td>表格数据</td>
</tr>
</table>
+
<iframe src="demo_iframe.htm"></iframe>
+
<form action="demo_form.php" method="post/get">
<input type="text" name="email" size="40" maxlength="50">
<input type="password">
<input type="checkbox" checked="checked">
<input type="radio" checked="checked">
<input type="submit" value="Send">
<input type="reset">
<input type="hidden">
<select>
<option>苹果</option>
<option selected="selected">香蕉</option>
<option>樱桃</option>
</select>
<textarea name="comment" rows="60" cols="20"></textarea>
</form>
+

HTML5 中的一些有趣的新特性

用于绘画的 canvas 元素

+

用于媒介回放的 videoaudio 元素

+

对本地离线存储的更好的支持

+

新的特殊内容元素,比如 article、footer、header、nav、section

+

新的表单控件,比如 calendar、date、time、email、url、search

+

IE9 以下版本浏览器兼容HTML5的方法:使用菜鸟教程的静态资源的html5shiv包

<!--[if lt IE9]>
<script src="http://cdn.static.runoob.com/libs/html5shiv/3.7/html5shiv.min.js"></script>
<![endif]-->

+

载入后,初始化新标签的CSS:

article,aside,dialog,footer,header,section,footer,nav,figure,menu{
display:block
}

+

html5shiv.js 引用代码必须放在<head>元素中,因为 IE 浏览器在解析 HTML5 新元素时需要先加载该文件。

+

字符实体

HTML 中的预留字符必须被替换为字符实体。

+

一些在键盘上找不到的字符也可以使用字符实体来替换。

+

HTML 中的常用字符实体是:

+
    +
  • 不间断空格 &nbsp;
  • +
  • 大于 &rt
  • +
  • 小于 &lt;
  • +
  • 引号 &quot;
  • +
  • 版权 ©`&#169;
  • +
  • 注册商标 &reg; &#174;
  • +
  • 商标 &trade;
  • +
+

URL - 统一资源定位器

Web浏览器通过URL从Web服务器请求页面。当您点击html页面中的某个链接时,对应的 <a>标签指向万维网上的一个地址。

+

一个统一资源定位器(URL) 用于定位万维网上的文档。

+

语法规则:

+

scheme://host.domain:port/path/filename

+

说明:

+
    +
  • scheme - 定义因特网服务的类型。最常见的类型是 http
  • +
  • host - 定义域主机(http 的默认主机是 www)
  • +
  • domain - 定义因特网域名,比如 runoob.com
  • +
  • :port - 定义主机上的端口号(http 的默认端口号是 80)
  • +
  • path - 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)。
  • +
  • filename - 定义文档/资源的名称
  • +
+]]>
- - web前端 - + web前端 - - - - - CSS - - - -
- - - - - HTML学习笔记 - - /posts/13b6b7c2/ - -

HTML学习笔记

HTML结构及常用元素

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
<head>
<title>文档标题</title>
</head>
<body>
可见文本...
</body>
</html>
1
2
3
4
5
6
<h1>最大的标题</h1>
<h2> . . . </h2>
<h3> . . . </h3>
<h4> . . . </h4>
<h5> . . . </h5>
<h6>最小的标题</h6>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<p>这是一个段落。</p>
<br> (换行)
<hr> (水平线)
<!-- 这是注释 -->
<b>粗体文本</b>
<code>计算机代码</code>
<em>强调文本</em>
<i>斜体文本</i>
<kbd>键盘输入</kbd>
<pre>预格式化文本</pre>
<small>更小的文本</small>
<strong>重要的文本</strong>
<abbr> (缩写)
<address> (联系信息)
<bdo> (文字方向)
<blockquote> (从另一个源引用的部分)
<cite> (工作的名称)
<del> (删除的文本)
<ins> (插入的文本)
<sub> (下标文本)
<sup> (上标文本)
普通的链接:<a href="http://www.example.com/">链接文本</a>
图像链接: <a href="http://www.example.com/"><img src="URL" alt="替换文本"></a>
邮件链接: <a href="mailto:webmaster@example.com">发送e-mail</a>
书签:
<a id="tips">提示部分</a>
<a href="#tips">跳到提示部分</a>
<img src="URL" alt="替换文本" height="42" width="42">

HTML实例代码

1
2
<div>文档中的块级元素</div>
<span>文档中的内联元素</span>
1
2
3
4
<ul>
<li>项目</li>
<li>项目</li>
</ul>
1
2
3
4
<ol>
<li>第一项</li>
<li>第二项</li>
</ol>
1
2
3
4
5
6
7
8
9
10
<table border="1">
<tr>
<th>表格标题</th>
<th>表格标题</th>
</tr>
<tr>
<td>表格数据</td>
<td>表格数据</td>
</tr>
</table>
1
<iframe src="demo_iframe.htm"></iframe>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<form action="demo_form.php" method="post/get">
<input type="text" name="email" size="40" maxlength="50">
<input type="password">
<input type="checkbox" checked="checked">
<input type="radio" checked="checked">
<input type="submit" value="Send">
<input type="reset">
<input type="hidden">
<select>
<option>苹果</option>
<option selected="selected">香蕉</option>
<option>樱桃</option>
</select>
<textarea name="comment" rows="60" cols="20"></textarea>
</form>

HTML5 中的一些有趣的新特性

用于绘画的 canvas 元素

用于媒介回放的 videoaudio 元素

对本地离线存储的更好的支持

新的特殊内容元素,比如 article、footer、header、nav、section

新的表单控件,比如 calendar、date、time、email、url、search

IE9 以下版本浏览器兼容HTML5的方法:使用菜鸟教程的静态资源的html5shiv包

1
2
3
<!--[if lt IE9]>
<script src="http://cdn.static.runoob.com/libs/html5shiv/3.7/html5shiv.min.js"></script>
<![endif]-->

载入后,初始化新标签的CSS:

1
2
3
article,aside,dialog,footer,header,section,footer,nav,figure,menu{
display:block
}

html5shiv.js 引用代码必须放在<head>元素中,因为 IE 浏览器在解析 HTML5 新元素时需要先加载该文件。

字符实体

HTML 中的预留字符必须被替换为字符实体。

一些在键盘上找不到的字符也可以使用字符实体来替换。

HTML 中的常用字符实体是:

  • 不间断空格 &nbsp;
  • 大于 &rt
  • 小于 &lt;
  • 引号 &quot;
  • 版权 ©`&#169;
  • 注册商标 &reg; &#174;
  • 商标 &trade;

URL - 统一资源定位器

Web浏览器通过URL从Web服务器请求页面。当您点击html页面中的某个链接时,对应的 <a>标签指向万维网上的一个地址。

一个统一资源定位器(URL) 用于定位万维网上的文档。

语法规则:

scheme://host.domain:port/path/filename

说明:

  • scheme - 定义因特网服务的类型。最常见的类型是 http
  • host - 定义域主机(http 的默认主机是 www)
  • domain - 定义因特网域名,比如 runoob.com
  • :port - 定义主机上的端口号(http 的默认端口号是 80)
  • path - 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)。
  • filename - 定义文档/资源的名称
]]>
- - + + HTML + +
+ + SEO学习笔记 + /posts/6021eb27/ +

SEO学习笔记

+

搜索引擎工作原理

+
+

SEO简介:

    +
  1. Search Engine Optimization 搜索引擎优化
  2. +
  3. 白帽SEO
  4. +
  5. 灰帽SEO
  6. +
+

白帽SEO(内容上的SEO):

    +
  1. 网站标题、关键字、描述
  2. +
  3. 网站内容优化
  4. +
  5. Robot.txt文件
  6. +
  7. 网站地图
  8. +
  9. 增加外链引用
  10. +
+ +

SEO注意要点:

    +
  • 结构布局优化:用扁平化结构(层次结构超过三层小蜘蛛就不愿意爬了)

    +
  • +
  • 控制首页链接数量(中小网站100以内,页面导航、底部导航、锚文字链接等)

    +
  • +
  • 扁平化的目录层次(小蜘蛛跳转3次可以到达网站内任何一个内页,网站的设计主页、栏目、内容页,不要用纵线性的结构)

    +
  • +
  • 导航seo优化(头部、底部、内容部分,主导航、副导航、分类导航,尽量用文字,面包屑导航,在每个网站上留下面包屑,使用户可以了解网站组织形式,放于正文的左上方)

    +
  • +
  • 内容页面的布局细节

    +
      +
    • 左面正文,右面热门文章、相关文章,下面是版权信息及链接,栏目排布:首页123456789下拉选择最赞)
    • +
    +
  • +
  • 网站的加载速度会影响小蜘蛛的爬行,页面最好不要超过100k

    +
  • +
  • 网页代码优化(语义化代码)

    +
      +
    • title标题:强调重点
    • +
    • meta keywords关键词:列举几个关键词/简洁高效词语
    • +
    • meta description网页描述:高度概括网页的内容
    • +
    • 以上信息不要堆积、重复
    • +
    +
  • +
+

有利搜索引擎

    +
  1. a:访问外部链接时要加上

    title 说明
    2. h1:搜索引擎外认为 h1 最重要,使用 css 调整,网页正文标题用 h1,副标题用 h2,其他不要乱用 h 标签
    3. br 用于文本间的换行,用在 p 内,也可以用 ```<p><br/></p> ```表示空行
    4. caption:表格标题
    5. img:使用 title、alt 说明
    6. ```<strong><em>```表示强调,```<em>```的权重仅次于```<strong>```,如果只想表示加粗斜体,建议使用```<b><i>```,表示强调则使用```<strong><em>

    +
  2. +
  3. 重要内容 HTML 代码放在最前面(使用 css 改变布局)

    +
  4. +
  5. 重要内容不要用 JS 输出(搜索引擎看不懂 JS)

    +
  6. +
  7. 尽量少使用 iframe 框架(搜索引擎不喜欢)

    +
  8. +
  9. 谨慎使用display:none(搜索引擎会过滤掉其内容,设置 z-index/text-index 代替)

    +
  10. +
  11. 精简代码

    +
  12. +
+]]>
- - web前端 - + web - - - - - HTML - - - -
- - - - - SEO学习笔记 - - /posts/6021eb27/ - -

SEO学习笔记

搜索引擎工作原理

SEO简介:

  1. Search Engine Optimization 搜索引擎优化
  2. 白帽SEO
  3. 灰帽SEO

白帽SEO(内容上的SEO):

  1. 网站标题、关键字、描述
  2. 网站内容优化
  3. Robot.txt文件
  4. 网站地图
  5. 增加外链引用

SEO注意要点:

  • 结构布局优化:用扁平化结构(层次结构超过三层小蜘蛛就不愿意爬了)

  • 控制首页链接数量(中小网站100以内,页面导航、底部导航、锚文字链接等)

  • 扁平化的目录层次(小蜘蛛跳转3次可以到达网站内任何一个内页,网站的设计主页、栏目、内容页,不要用纵线性的结构)

  • 导航seo优化(头部、底部、内容部分,主导航、副导航、分类导航,尽量用文字,面包屑导航,在每个网站上留下面包屑,使用户可以了解网站组织形式,放于正文的左上方)

  • 内容页面的布局细节

    • 左面正文,右面热门文章、相关文章,下面是版权信息及链接,栏目排布:首页123456789下拉选择最赞)
  • 网站的加载速度会影响小蜘蛛的爬行,页面最好不要超过100k

  • 网页代码优化(语义化代码)

    • title标题:强调重点
    • meta keywords关键词:列举几个关键词/简洁高效词语
    • meta description网页描述:高度概括网页的内容
    • 以上信息不要堆积、重复

有利搜索引擎

  1. a:访问外部链接时要加上

    title 说明
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    2. h1:搜索引擎外认为 h1 最重要,使用 css 调整,网页正文标题用 h1,副标题用 h2,其他不要乱用 h 标签
    3. br 用于文本间的换行,用在 p 内,也可以用 ```<p><br/></p> ```表示空行
    4. caption:表格标题
    5. img:使用 title、alt 说明
    6. ```<strong><em>```表示强调,```<em>```的权重仅次于```<strong>```,如果只想表示加粗斜体,建议使用```<b><i>```,表示强调则使用```<strong><em>

  2. 重要内容 HTML 代码放在最前面(使用 css 改变布局)

  3. 重要内容不要用 JS 输出(搜索引擎看不懂 JS)

  4. 尽量少使用 iframe 框架(搜索引擎不喜欢)

  5. 谨慎使用display:none(搜索引擎会过滤掉其内容,设置 z-index/text-index 代替)

  6. 精简代码

]]>
- - + + seo + +
+ + 提升效率 + /posts/8786024c/ +

提升效率

+

在前进的路上,放弃那些次要的、可有可无的东西,获取真正重要、有意义的价值,让自己更加认同自己的付出和努力方向,这才是时间管理的本质和最大意义所在。

+
+

必须学会说“不”

说“不”其实是个非常艰难的事情,可是如果不说no,那么就很难专心地应对真正重要的任务。因为有太多看起来不错的机会、看上去不能拒绝的要求、事成后有利的图景,以及无法拒绝的人情世故,诱惑着你答应下来。

+

其实工作越久,你就越会发现,真正的牛人,往往就牛在敢于放弃上。所谓的战略化决策,不仅仅是指战略高度的选择,也指战略高度的放弃。刚开始放弃的时候会很难受,这是多年形成的习惯和求全责备的心态发出的尖叫和抗议。可是时间久了才发现:不重要的事情真做不完也不会死,倒是重要的事情老拖着不做往往会后果比较严重。

+ +

必须学会说yes

对我而言,如果想要找时间完成真正重要的事情,那么就先答应下来,再商量个相对宽裕的时间。将这些定下来之后,我总能想出方法,排除万难去实践。

+

无论是写小说、开公众号、参加考试,都可以遵循这个套路。牺牲掉部分娱乐、睡眠、社交,甚至是和家人团聚的时间,会非常适合短期内的明确目标,并督促你用冲刺的方式完成。

+

如果一件事情并不重要,那么就明确地拒绝;如果很重要,就大胆地接受。你不会因为说“不”损失多少,也不会因为应承去做却没有做好而损失很多。真正的损失是在我们说“这事儿很好,我再想想”中发生的。

+

金钱换时间

以前没有孩子的时候,我习惯利用整块时间写作,写作进入状态也非常缓慢,必须要在阳光充足的某个角落坐下,泡杯咖啡,看看新闻,再慢慢进入状态。

+

现在可用的业余时间往往是零散的,如果不能抓住零散时间进行思考和打草稿,那就更没有时间了。为了能更好地抓住这些碎片时间,我添置了更多的电子设备,例如静音且无须插电源的平板电脑,它能让我更好地利用孩子入睡后的时间。再比如我打破了从前不下载App的习惯,安装了多个阅读、记录、拍照笔记类的App,方便自己在零碎时间里能随时把读到的、想到的、看到的、诱发灵感的材料都尽快地收纳进来。

+

找到时间后,就是筹划和管理时间了。

+

关掉提醒,高效专注地工作

要想工作有效,就必须运用整块的时间。如果将时间分割开来零星使用,纵然时间总和相同,但其效果与整块运用时间的效果却差距很大。比如我以前工作时常要写一些措辞讲究的英文邮件,如果能够聚精会神地写,再加上润色,十几分钟就能完成。可是我总会忍不住一边写一边去看看什么人又说了什么话,有时还会因为查某个单词去逛下红迪网。

+

后来实在忙起来了,任凭各种新信息提醒也不去查看,等到某个任务告一段落,再统一查看和回复,既保证了效率,又不至于错过什么。仅这一项小小的改变,就大大提高了我的工作效率。

+

减少选项,设置优先级

选项越少,时间越多。一个比较经典的时间管理方法是:每天只选择1~3件事情去做,并辅以不懈地追求。你的本能不会喜欢这样的限制,可是这种方法有利于排列真正重要的事情,比起事无巨细地齐头并进,能让工作更为出色。

+

提前把你想到的写下来

当事情一旦多了杂了,脑子就明显不够用。我经常发现,哪怕是小事,如果写下来就会遵守;不写,无论在脑子里想多久,一被打扰就会忘掉。提前计划的目的其实不是为了“计划”,而是为了更重视时间的流向,知道时间都花到哪里去了。

+

如果不是很清晰地知道要做什么,就容易碰到什么是什么。于是哪件事情先找上来就先处理了,就好比我特别反感邮箱,因为邮件不停地进来,叮的一声响。只要邮箱的叮声不关,我就永远干不了该干的事情,会一直挂在邮箱上回复邮件,而且要一会儿回邮件,一会儿写报告,一会儿又查数据。数据查到一半叮的一声邮件又进来了,说到了另一件事,再去查……忙了一上午,几件重要的大事却一件都没干。

+

先把所有需要完成的事列出来,然后对大任务进行分解,分解成小一些的子任务,再对任务进行排序。排序时最艰难的步骤就是决定放弃或者推迟哪些东西。

+

找到适合自己的好方法

开始时间管理的时候,大家都会热衷于搜罗和学习各种方法。比如有一种著名的战拖策略叫作“吃掉那只青蛙”,鼓励大家给最重要、最困难的任务以第一优先权。但是我在实践之后,却发现这个方法极其不适合我。因为如果一上来就强迫自己完成最艰巨的任务,我反而会容易知难而退,会造成各种拖延。所以我摸索出的合适自己的方法是先完成最简单、最有兴趣的工作,通过这些初级工作渐入佳境,等效率上来了,再去啃“坚硬的骨头”。

+

说到这里,时间管理却还不能结束。桥本和彦曾经说过,“没有体现结果的时间管理就不能称之为时间管理”,因此定期对时间管理的成就和不足之处进行反思,就有非常重要的意义。

+

坚持时间管理最大的挑战就在于:即便你用最高科技的工具,按照最合理的科学方法、符合生物钟的方法规划好了时间,然后恪守,一天下来有很大的收获,你的内心也在呼唤你歪倒在沙发上刷手机、追美剧、和朋友瞎聊。

+

为了战胜无时不在的诱惑,就需要时不时地重温一下目标,配合着各种短期、中期、长期的目标,时间管理上也应相应配合着进行松弛有度的分布。任何时间管理和战拖秘诀都离不开恒心,但是生活必须要张弛有度。

+

如果是学生为了考GRE,那么两个月的短期突击式的冲刺,要比断断续续地复习一年有效;而大考完毕,可以有一小段时间让大脑放松下,以便进入下一阶段的目标。

+

一个人如果长期无目标地疲劳战斗,那么时间管理便会沦为空谈,你依旧会身心俱疲且内心无比迷茫,那样的话还不如好好歇着。

+

当然,如果把时间管理放到整个人生来看,有些人喜欢有计划、高产高效的生活,也有人喜欢随性自由的节奏。这些都没有问题,你尽可以按自己的喜好选择自己喜欢的方式。不过要记住,每种选择都意味着相应的放弃,只要回过头时不会患得患失就好。

+

对很多人而言,时间管理也是一种成就。他们对时间管理的追求,就是对成就感的追求,这也是他们进行时间管理的最大动力。

+

如果是这种情况,那么拥有一个能完成后打钩的to-dolist(待办事项列表)或者任务工作本、相关任务管理App,让这种成就可视化,就是很好的选择。

+

对我个人而言,时间管理的最大成功,不是达成了什么了不起的大成就,而是让自己能更明晰时间的去向、对事物的价值度有所衡量,并通过“管理时间”这一具体行动,让自己不再盲目焦虑。

+

总结

在前进的路上,放弃那些次要的、可有可无的东西,获取真正重要、有意义的价值,让自己更加认同自己的付出和努力方向,这才是时间管理的本质和最大意义所在。

+]]>
- - web - + 方法论 - - - - - seo - - - -
- - - - - 提升效率 - - /posts/8786024c/ - -

提升效率

在前进的路上,放弃那些次要的、可有可无的东西,获取真正重要、有意义的价值,让自己更加认同自己的付出和努力方向,这才是时间管理的本质和最大意义所在。

必须学会说“不”

说“不”其实是个非常艰难的事情,可是如果不说no,那么就很难专心地应对真正重要的任务。因为有太多看起来不错的机会、看上去不能拒绝的要求、事成后有利的图景,以及无法拒绝的人情世故,诱惑着你答应下来。

其实工作越久,你就越会发现,真正的牛人,往往就牛在敢于放弃上。所谓的战略化决策,不仅仅是指战略高度的选择,也指战略高度的放弃。刚开始放弃的时候会很难受,这是多年形成的习惯和求全责备的心态发出的尖叫和抗议。可是时间久了才发现:不重要的事情真做不完也不会死,倒是重要的事情老拖着不做往往会后果比较严重。

必须学会说yes

对我而言,如果想要找时间完成真正重要的事情,那么就先答应下来,再商量个相对宽裕的时间。将这些定下来之后,我总能想出方法,排除万难去实践。

无论是写小说、开公众号、参加考试,都可以遵循这个套路。牺牲掉部分娱乐、睡眠、社交,甚至是和家人团聚的时间,会非常适合短期内的明确目标,并督促你用冲刺的方式完成。

如果一件事情并不重要,那么就明确地拒绝;如果很重要,就大胆地接受。你不会因为说“不”损失多少,也不会因为应承去做却没有做好而损失很多。真正的损失是在我们说“这事儿很好,我再想想”中发生的。

金钱换时间

以前没有孩子的时候,我习惯利用整块时间写作,写作进入状态也非常缓慢,必须要在阳光充足的某个角落坐下,泡杯咖啡,看看新闻,再慢慢进入状态。

现在可用的业余时间往往是零散的,如果不能抓住零散时间进行思考和打草稿,那就更没有时间了。为了能更好地抓住这些碎片时间,我添置了更多的电子设备,例如静音且无须插电源的平板电脑,它能让我更好地利用孩子入睡后的时间。再比如我打破了从前不下载App的习惯,安装了多个阅读、记录、拍照笔记类的App,方便自己在零碎时间里能随时把读到的、想到的、看到的、诱发灵感的材料都尽快地收纳进来。

找到时间后,就是筹划和管理时间了。

关掉提醒,高效专注地工作

要想工作有效,就必须运用整块的时间。如果将时间分割开来零星使用,纵然时间总和相同,但其效果与整块运用时间的效果却差距很大。比如我以前工作时常要写一些措辞讲究的英文邮件,如果能够聚精会神地写,再加上润色,十几分钟就能完成。可是我总会忍不住一边写一边去看看什么人又说了什么话,有时还会因为查某个单词去逛下红迪网。

后来实在忙起来了,任凭各种新信息提醒也不去查看,等到某个任务告一段落,再统一查看和回复,既保证了效率,又不至于错过什么。仅这一项小小的改变,就大大提高了我的工作效率。

减少选项,设置优先级

选项越少,时间越多。一个比较经典的时间管理方法是:每天只选择1~3件事情去做,并辅以不懈地追求。你的本能不会喜欢这样的限制,可是这种方法有利于排列真正重要的事情,比起事无巨细地齐头并进,能让工作更为出色。

提前把你想到的写下来

当事情一旦多了杂了,脑子就明显不够用。我经常发现,哪怕是小事,如果写下来就会遵守;不写,无论在脑子里想多久,一被打扰就会忘掉。提前计划的目的其实不是为了“计划”,而是为了更重视时间的流向,知道时间都花到哪里去了。

如果不是很清晰地知道要做什么,就容易碰到什么是什么。于是哪件事情先找上来就先处理了,就好比我特别反感邮箱,因为邮件不停地进来,叮的一声响。只要邮箱的叮声不关,我就永远干不了该干的事情,会一直挂在邮箱上回复邮件,而且要一会儿回邮件,一会儿写报告,一会儿又查数据。数据查到一半叮的一声邮件又进来了,说到了另一件事,再去查……忙了一上午,几件重要的大事却一件都没干。

先把所有需要完成的事列出来,然后对大任务进行分解,分解成小一些的子任务,再对任务进行排序。排序时最艰难的步骤就是决定放弃或者推迟哪些东西。

找到适合自己的好方法

开始时间管理的时候,大家都会热衷于搜罗和学习各种方法。比如有一种著名的战拖策略叫作“吃掉那只青蛙”,鼓励大家给最重要、最困难的任务以第一优先权。但是我在实践之后,却发现这个方法极其不适合我。因为如果一上来就强迫自己完成最艰巨的任务,我反而会容易知难而退,会造成各种拖延。所以我摸索出的合适自己的方法是先完成最简单、最有兴趣的工作,通过这些初级工作渐入佳境,等效率上来了,再去啃“坚硬的骨头”。

说到这里,时间管理却还不能结束。桥本和彦曾经说过,“没有体现结果的时间管理就不能称之为时间管理”,因此定期对时间管理的成就和不足之处进行反思,就有非常重要的意义。

坚持时间管理最大的挑战就在于:即便你用最高科技的工具,按照最合理的科学方法、符合生物钟的方法规划好了时间,然后恪守,一天下来有很大的收获,你的内心也在呼唤你歪倒在沙发上刷手机、追美剧、和朋友瞎聊。

为了战胜无时不在的诱惑,就需要时不时地重温一下目标,配合着各种短期、中期、长期的目标,时间管理上也应相应配合着进行松弛有度的分布。任何时间管理和战拖秘诀都离不开恒心,但是生活必须要张弛有度。

如果是学生为了考GRE,那么两个月的短期突击式的冲刺,要比断断续续地复习一年有效;而大考完毕,可以有一小段时间让大脑放松下,以便进入下一阶段的目标。

一个人如果长期无目标地疲劳战斗,那么时间管理便会沦为空谈,你依旧会身心俱疲且内心无比迷茫,那样的话还不如好好歇着。

当然,如果把时间管理放到整个人生来看,有些人喜欢有计划、高产高效的生活,也有人喜欢随性自由的节奏。这些都没有问题,你尽可以按自己的喜好选择自己喜欢的方式。不过要记住,每种选择都意味着相应的放弃,只要回过头时不会患得患失就好。

对很多人而言,时间管理也是一种成就。他们对时间管理的追求,就是对成就感的追求,这也是他们进行时间管理的最大动力。

如果是这种情况,那么拥有一个能完成后打钩的to-dolist(待办事项列表)或者任务工作本、相关任务管理App,让这种成就可视化,就是很好的选择。

对我个人而言,时间管理的最大成功,不是达成了什么了不起的大成就,而是让自己能更明晰时间的去向、对事物的价值度有所衡量,并通过“管理时间”这一具体行动,让自己不再盲目焦虑。

总结

在前进的路上,放弃那些次要的、可有可无的东西,获取真正重要、有意义的价值,让自己更加认同自己的付出和努力方向,这才是时间管理的本质和最大意义所在。

]]>
- - + + 方法论 + +
+ + 学习新技术建议 + /posts/a5b005af/ +

学习新技术建议

+

我们生活在一个振奋人心的时代。我们可以越来越方便廉价地获得大量学习资源。这些资源的传播载体由最初的教室被变成了博客,技术论坛等。坐拥如此众多的学习资源,我们没有任何理由不去好好利用。随之而来的问题便是如何在这知识的海洋中选择自己的前进方向。
尽管我的建议主要涉及的是软件开发方面,但是这些原则在其他领域也同样适用。

+
+ +

克服惯性

万事开头难,克服惯性是学习新技术的第一步。举个日常生活中惯性存在的简单栗子,当我们看电视的时候会因为遥控器不在身边而懒得换台。幸运的是有很多的小技巧可以调动我们的积极性,帮助我们克服惯性。对于我来说,微习惯是一个很好用的小技巧。与其被手头的任务吓到,不如将任务细分为一个个具体的微任务,然后挑选其中的一个开始做起。就“拿到遥控器”这个例子来说,首先扭动你的脚趾,向前伸出,然后推动整个人离开沙发。下一步,身体滑到地上,用脚拿到遥控器,然后起身。通过完成一个个的微任务,你会发现自己克服了惯性,并且这项任务不再显得难以完成。这个方法可以被应用到学习新技能的过程中。关键就是将大块任务细分为微任务。

+

关注大牛

学习新技能的第一步是明确要学什么。它可以是任何你有激情去学,并且想深入学习的一些东西。这种原始的学习欲望非常重要,这种欲望可以在你的学习低潮期给你提供动力。你想学的或许是一门新的编程语言、应用框架或者是新的工具,一旦你确定了想要的是什么,就立刻去收集相应的优秀群体所做的一些优质的工作成果。这些可以从YouTube、Vimeo、HackerNews、各种博客,甚至是你的微博好友那里获取。关注别人做了些什么可以给你强大的信心,让你觉得 “You can do it, too!”

+

建立知识网

当你对自己要学习的东西建立了信心之后,接下来要做的就是做一块海绵,然后开始疯狂地吸收知识。从Google搜索关键词“beginner tutorials”开始吧,搜索一些跟你要学习的知识相关的入门教程。如你所知,Nettuts+上面有成千上百的各种教程供你选择,StackOverflow上面也有很多学习资源。此外,Quora也是一些不错的选择。通过浏览这些网上的资源之后,如果想要集中精力学习某一方面,这时就需要阅读一些相关的书籍了,个人推荐在Amazon上面寻找一些评分较高的专业书籍来提高自己。

+

多听多看

随着你对技术的深入挖掘,你可能会想利用更多其他形式的学习资料,比如podcasts,screencasts等等。我的建议是多用 iTunesU,这上面有很多很专业的知识可以让你对于特定的领域进行深入的探索。

+

可以看一些免费的会议视频材料,比如YouTube上面的Google IO,以及Confreaks!

+

行动起来

现在你已经看了一波又一波的教程以及视频资料,并且对于想学的技术已经有了一个相当深入的了解,接下来做些什么呢?没错,是时候理论联系实际了,实践是检验真理的唯一标准。

+

用你所掌握的技术做一个个人的小项目,设计一些简单的功能并且实现他们。毫无疑问,你会遇到很多的绊脚石,当遇到它们的时候,在StackOverflow或者Google上面搜索之,解决之。你已经踏上一条成为某一领域专家的旅程,遇到的困难挫折越多,你会变得越睿智。有句老话说得好,“专家是犯错最多的人”,这意味着他们尝试了很多疯狂的事情来探索这门技术的极限,最后,对于这门技术是如何运作的就可以知根知底。拥有这种洞察力之后,他们便可以随心所欲的运用这项技术去按照自己的意愿完成想做的事情(当然,是做好的事情)。

+

写博客

在你进行你的探险之旅的时候,实时记录下你的成长以及犯下的错误大有裨益。在技术领域,博客是最简单易得并且受欢迎的表达载体。当你准备落笔的时候,你会强迫自己整理思路,并且对积累下来的零散的知识片段进行结构梳理。说不定,通过互联网的分享,你的经历和分享会给别人的成长带来帮助。

+

如果你想走的更远(比如想像Nettuts+上面的职业作者一样),你也可以制作属于自己的screencasts。总的来说,写博客能够提升你的个人沟通能力,这与你学到的技术同样重要。

+

感受技术的脉搏

社交网络已经广泛应用于人们的日常交流以及发现新鲜事物。Twitter和Facebook是信息的主要来源,与此同时,有很多的网站提供更专注的资讯,如前面提到过的Quora网站,这上面有很多涉及面很广的一些话题供人们评论。在这上面可以找到很多知名大牛的建议以及观点。

+

浏览StackOverflow上面的众多话题是一个很有意思的过程,你可以看到他人如何探索某种技术的极限。事实上,在人们利用技术做一些疯狂的甚至是荒诞的事情的时候,技术也随之不断的成熟起来。

+

因此,如果你想要感受到技术的脉搏,并且想确认它是否值得学下去,在StackOverflow上面试着搜索一些话题,看看这个讨论社区的广度与深度。最值得看的是投票最多以及热门话题。你也可以尝试在GitHub上面进行搜索。

+

参加聚会以及会议

尽管社交网络很棒,但是没有任何事物可以取代面对面的交流。在你住的附近参加一些小组聚会,在这里你可以找到志同道合的伙伴。你可以知道他人在做的一些有趣的项目,同时也可以在他人的帮助下解决一些自己遇到的难题!同样的,技术会议对于分享经验以及增长技术大有帮助!

+

拥抱 GitHub

GitHub是全世界开源项目的标志性建筑物。它是知识以及优质代码的宝库。当你对某项技术自我感觉良好的时候,下一步便是在GitHub中浏览寻找有趣的项目。阅读开源代码,尽可能多的阅读。这样做的话,你能够学到很多东西,比如说:

+
    +
  • 如何管理规模较大的项目
  • +
  • 项目中应用的有趣的库
  • +
  • 代码规范以及代码全局设计
  • +
  • 文档风格
  • +
  • 测试规范
  • +
  • 解决诡异问题的方法,以及发现项目中有问题的地方
  • +
+

所有的这些知识都在等待着你去挖掘。有趣的是,这些知识的通过一个简单的标签就可以得到,那就是“好奇心”。

+

专注学习

如果你担心上述的学习过程太迟缓,那么你也可以尝试一下快速学习模式。你或许听说过“24小时学会某某某”,但是这种方式不是我所推荐的。我认为更合理的是用几周的时间去学习。你可以尝试一下类似“七周学会七种语言”或者是“七周学会七种数据库”等学习方法。尽管这些讲的是语言以及数据库方面的学习,但是你在学习其他技术的时候也可以运用这种思维。

+

有一个不太相同的学习风格是“困难学习模式”,这种观点的前提是没有人可以真正掌握一门技术,除非每天都练习。所以,想要成为专家,你就需要不停地进行练习。异曲同工的是你可以查看Katas 和 Koans,他鼓励的使用你学的知识来解决问题。这些可以让你更好地入门以及接受那些陌生的概念,勇敢走出自己的舒适区,开始学习新知识!

+

学习一门交叉的技能

编程是一项左脑的运动,它利用的是大脑的分析能力,一步一步地寻找解决问题的方法。为了发挥右脑的功能,你可以尝试从事一些创造性的活动,比如说画画、3D建模、折纸、乐器甚至是制作家庭相册等。事实上,编程同样需要大量的创造力。或许你曾经遇到过类似的事情,你在睡梦中找到了问题的解决方案。这是因为你的右脑处理问题的方式很不同,它可以从各种地方获得信息。敏捷开发权威人士Andy Hunt就这个话题写了一本书《程序员的思维修炼》。如果你想点燃你的每一个神经元,建议你开始学习一门交叉的技能。

+

不害怕探索陌生程序语言

接触新专案或是转换工作跑道时,都有可能需要学习全然陌生的程序语言,许多人对此感到害怕,甚至未尝试就先放弃。其中,跳脱舒适圈的恐惧往往多于学习程序,会担心是否无法重现过去工作的好表现,甚至因此怀疑自身能力。

+

不论是多厉害的工程师,一定都有起点,就像打造Microsoft Windows基础的微软资深工程师Dave Cutler为文组出身,没受过正式电脑科学教育,比起同辈花更多时间在错误中学习。

+

在这之中,最重要的两个关键为具备「成长心态」(growth-mindset)而非「固守心态」(fixed-mindset),以及「乐于学习」(optimize for learning)的态度。

+

学习陌生程序语言这项关键能力会越练越上手,并让你在学习过程中成为更好的程序设计师。

+

精通Debug

为什麽程序跑出来和我预期的不一样?
是许多工程师会遇到的问题。Debug能力往往是影响工程师是否能顺利完成专案的关键因素,却被大部分人低估。

+

Debug的系统性思考如下:

+
    +
  • 先假设造成bug的可能原因。
  • +
  • 若假设为真,界定此假设可能导致的结果。
  • +
  • 试著检视是否有和这些结果衝突的现象。
  • +
  • 若有衝突表示假设错误,要重複上述思考过程。
  • +
+

由此可知,想加快Debug速度,要提升「提出假设」和「检视假设」的能力。假设能力可随著Debug经验的累积而提升,检视能力则需加强善用检测工具的技能。

+

在此过程,必须先假设所有东西都是可检视的,并找出可用来检测或加快检测速度的工具或机制,千万不要只用自己熟悉的工具。

+

开发节省时间的工具

减少时间做那些电脑就可做的工作,例如开发节省时间的工具和使工作流程自动化。

+

曾负责Facebook软件基础建设团队的软件工程师Bobby Johnson,带领该团队从6人成长至超过1百人。他观察到,团队中表现出色的人多数写了许多工具,这些看似和绩效无直接相关的工具开发时间可能佔三分之一的工作时间,却因此大大提升工作效率,其中包含用来部署程序、监测系统,以及其他可节省时间的工具。

+

优化重复性工作的速度

软件工程师每天可能要搜寻、浏览函数定义很多次,善用键盘快捷键可省下可观的时间。

+

例如,每次搜寻需花12秒,类似的步骤每天要重複20次,若用快捷键可将搜寻时间缩短到2秒,一年下来即省了40个小时。其他状况如每次Debug都需要在不同装置测试,除了要分别打开app,还要设定测试情境,这时候就可以思考如何加快这类重複性工作的速度。

+

发展系统性思考模式

写完程序码、让程序可运作仅是冰山一角,要产出真正有价值的程序,必须从程序本身提升到整个系统来思考。

+
    +
  • 你的程序和其他程序库以及其他人写的功能是否相容?
  • +
  • 程序是否测试完成,并确保其他成员可执行你写的这些功能?
  • +
  • 部署你的程序需要改变哪些生产环境?
  • +
  • 新程序对其他正在运作的系统是否有负面影响?
  • +
  • 客户和使用者的新程序使用情况是否如预期?
  • +
  • 新程序是否达到公司期待的效果?
  • +
+

固定型思维模式改变的四个方法。

对称赞和成功进行认知转换

第一,对称赞和成功进行认知转换。转换对称赞的认知,我的意思是当你获得错误方式的称赞时,将它们转换为有利成长型思维模式的称赞。因此如果有人说“哇,你的工作做得真好,你太聪明了!”,你可以将它转换为“耶!太好了,我在这个项目中真努力!”。你没必要大声地喊出来!但是认知转换能让你提高寻求挑战和付出努力的主动性!

+

你可以在成功或成就中采用相同的方式。当一些事情进行的顺利的时候,不要觉得“当然会做的很好因为我聪明啊”,而是想“我在这个项目中采用了一个有效的方法!我应该更多地去应用这个方法”。

+

转换对失败的认知

第二,转换对失败的认知。当然这个方法的另一面也非常有效。固定型思维模式和成长型思维模式的很大一部分是你怎样应对失败。当你面对挫折或者没有得到你想要的结果时,你的内心戏是怎么样的?如果你觉得“可能我确实不适合这份工作”,这时应该用红色小旗做标识。与此相反,你应该问问你从你的失败中得到了什么或者哪种学习方式你需要改变。这个方法听起来很平常,但是真的很有用。

+

为挑战庆幸

第三,为挑战庆幸。当你必须竞争的时候你是什么样的反应?试着为此感到庆幸。这是我在Recurse Center工作时始终坚持的习惯。一些人会坐在我旁边说:“我遇到一个奇葩的Python bug(叹气)”。 我说:“太好了,我就喜欢奇葩的python bugs!”。首先,让我们来说说,有一点是清楚的——当你遇到一个奇葩的bug,相对于bug本身更重要的是,这说明你找到了一些可以通过努力获得成就感的事情,这些事情是你可遇不可求的。

+

像我提到的一样,在Recurse Center没有交付日期,没有任务分配,因此这种心态是无需付出任何代价的。我一般会说“你可以花一天时间在Flask(python的一个框架)上追踪这个bug,多好啊!”现在,在Dropbox(一种云存储服务)上,我们有一个产品要开发,有交付日期和相应用户。我不能总是一味地为花一天时间来为追踪bug感到高兴。因此,我对身处有交付日期的现实中的人们深感同情。然而,如果我必须修复一个漏洞,我承认bug的存在不利于我对漏洞的修复。但是在没有交付日期的情况下,你仍然可以采用我的态度。

+

关注过程

第四,关注过程。跟很多人一样,我同一些优秀的工程师一起工作。有时,我会试着用不合理的方式修复一些棘手的bug,但是有些人能够以正确的方式修复。在这种情况下,我会习惯性地问他们怎么做到的。尤其当我刚用Dropbox的时候,他们的回答会很有启发性。有时,他们回答的一些信息来自于我根本不知道的知识中。现在,我在这里待得久了,经常看到和别人技术和方法上的不同,或者发现一些自己的方式之所以不能成功的细节。

+

这种方法对于总是觉得:“这个人能解决这个bug一定是个天才!”的一类人,是长期最有效的。

+

总结

掌握一门新技术振奋人心,这是一项影响你思维的新的体验。但是首先,你必须克服你的惯性,一旦你做到了,你便开启了从web的每个角落学习知识的旅程。我希望上面讲的十点能够给你的旅程带来一些帮助或启发。

+]]>
- - 方法论 - + 方法论 - - - - - 方法论 - - - -
- - - - - 学习新技术建议 - - /posts/a5b005af/ - -

学习新技术建议

我们生活在一个振奋人心的时代。我们可以越来越方便廉价地获得大量学习资源。这些资源的传播载体由最初的教室被变成了博客,技术论坛等。坐拥如此众多的学习资源,我们没有任何理由不去好好利用。随之而来的问题便是如何在这知识的海洋中选择自己的前进方向。
尽管我的建议主要涉及的是软件开发方面,但是这些原则在其他领域也同样适用。

克服惯性

万事开头难,克服惯性是学习新技术的第一步。举个日常生活中惯性存在的简单栗子,当我们看电视的时候会因为遥控器不在身边而懒得换台。幸运的是有很多的小技巧可以调动我们的积极性,帮助我们克服惯性。对于我来说,微习惯是一个很好用的小技巧。与其被手头的任务吓到,不如将任务细分为一个个具体的微任务,然后挑选其中的一个开始做起。就“拿到遥控器”这个例子来说,首先扭动你的脚趾,向前伸出,然后推动整个人离开沙发。下一步,身体滑到地上,用脚拿到遥控器,然后起身。通过完成一个个的微任务,你会发现自己克服了惯性,并且这项任务不再显得难以完成。这个方法可以被应用到学习新技能的过程中。关键就是将大块任务细分为微任务。

关注大牛

学习新技能的第一步是明确要学什么。它可以是任何你有激情去学,并且想深入学习的一些东西。这种原始的学习欲望非常重要,这种欲望可以在你的学习低潮期给你提供动力。你想学的或许是一门新的编程语言、应用框架或者是新的工具,一旦你确定了想要的是什么,就立刻去收集相应的优秀群体所做的一些优质的工作成果。这些可以从YouTube、Vimeo、HackerNews、各种博客,甚至是你的微博好友那里获取。关注别人做了些什么可以给你强大的信心,让你觉得 “You can do it, too!”

建立知识网

当你对自己要学习的东西建立了信心之后,接下来要做的就是做一块海绵,然后开始疯狂地吸收知识。从Google搜索关键词“beginner tutorials”开始吧,搜索一些跟你要学习的知识相关的入门教程。如你所知,Nettuts+上面有成千上百的各种教程供你选择,StackOverflow上面也有很多学习资源。此外,Quora也是一些不错的选择。通过浏览这些网上的资源之后,如果想要集中精力学习某一方面,这时就需要阅读一些相关的书籍了,个人推荐在Amazon上面寻找一些评分较高的专业书籍来提高自己。

多听多看

随着你对技术的深入挖掘,你可能会想利用更多其他形式的学习资料,比如podcasts,screencasts等等。我的建议是多用 iTunesU,这上面有很多很专业的知识可以让你对于特定的领域进行深入的探索。

可以看一些免费的会议视频材料,比如YouTube上面的Google IO,以及Confreaks!

行动起来

现在你已经看了一波又一波的教程以及视频资料,并且对于想学的技术已经有了一个相当深入的了解,接下来做些什么呢?没错,是时候理论联系实际了,实践是检验真理的唯一标准。

用你所掌握的技术做一个个人的小项目,设计一些简单的功能并且实现他们。毫无疑问,你会遇到很多的绊脚石,当遇到它们的时候,在StackOverflow或者Google上面搜索之,解决之。你已经踏上一条成为某一领域专家的旅程,遇到的困难挫折越多,你会变得越睿智。有句老话说得好,“专家是犯错最多的人”,这意味着他们尝试了很多疯狂的事情来探索这门技术的极限,最后,对于这门技术是如何运作的就可以知根知底。拥有这种洞察力之后,他们便可以随心所欲的运用这项技术去按照自己的意愿完成想做的事情(当然,是做好的事情)。

写博客

在你进行你的探险之旅的时候,实时记录下你的成长以及犯下的错误大有裨益。在技术领域,博客是最简单易得并且受欢迎的表达载体。当你准备落笔的时候,你会强迫自己整理思路,并且对积累下来的零散的知识片段进行结构梳理。说不定,通过互联网的分享,你的经历和分享会给别人的成长带来帮助。

如果你想走的更远(比如想像Nettuts+上面的职业作者一样),你也可以制作属于自己的screencasts。总的来说,写博客能够提升你的个人沟通能力,这与你学到的技术同样重要。

感受技术的脉搏

社交网络已经广泛应用于人们的日常交流以及发现新鲜事物。Twitter和Facebook是信息的主要来源,与此同时,有很多的网站提供更专注的资讯,如前面提到过的Quora网站,这上面有很多涉及面很广的一些话题供人们评论。在这上面可以找到很多知名大牛的建议以及观点。

浏览StackOverflow上面的众多话题是一个很有意思的过程,你可以看到他人如何探索某种技术的极限。事实上,在人们利用技术做一些疯狂的甚至是荒诞的事情的时候,技术也随之不断的成熟起来。

因此,如果你想要感受到技术的脉搏,并且想确认它是否值得学下去,在StackOverflow上面试着搜索一些话题,看看这个讨论社区的广度与深度。最值得看的是投票最多以及热门话题。你也可以尝试在GitHub上面进行搜索。

参加聚会以及会议

尽管社交网络很棒,但是没有任何事物可以取代面对面的交流。在你住的附近参加一些小组聚会,在这里你可以找到志同道合的伙伴。你可以知道他人在做的一些有趣的项目,同时也可以在他人的帮助下解决一些自己遇到的难题!同样的,技术会议对于分享经验以及增长技术大有帮助!

拥抱 GitHub

GitHub是全世界开源项目的标志性建筑物。它是知识以及优质代码的宝库。当你对某项技术自我感觉良好的时候,下一步便是在GitHub中浏览寻找有趣的项目。阅读开源代码,尽可能多的阅读。这样做的话,你能够学到很多东西,比如说:

  • 如何管理规模较大的项目
  • 项目中应用的有趣的库
  • 代码规范以及代码全局设计
  • 文档风格
  • 测试规范
  • 解决诡异问题的方法,以及发现项目中有问题的地方

所有的这些知识都在等待着你去挖掘。有趣的是,这些知识的通过一个简单的标签就可以得到,那就是“好奇心”。

专注学习

如果你担心上述的学习过程太迟缓,那么你也可以尝试一下快速学习模式。你或许听说过“24小时学会某某某”,但是这种方式不是我所推荐的。我认为更合理的是用几周的时间去学习。你可以尝试一下类似“七周学会七种语言”或者是“七周学会七种数据库”等学习方法。尽管这些讲的是语言以及数据库方面的学习,但是你在学习其他技术的时候也可以运用这种思维。

有一个不太相同的学习风格是“困难学习模式”,这种观点的前提是没有人可以真正掌握一门技术,除非每天都练习。所以,想要成为专家,你就需要不停地进行练习。异曲同工的是你可以查看Katas 和 Koans,他鼓励的使用你学的知识来解决问题。这些可以让你更好地入门以及接受那些陌生的概念,勇敢走出自己的舒适区,开始学习新知识!

学习一门交叉的技能

编程是一项左脑的运动,它利用的是大脑的分析能力,一步一步地寻找解决问题的方法。为了发挥右脑的功能,你可以尝试从事一些创造性的活动,比如说画画、3D建模、折纸、乐器甚至是制作家庭相册等。事实上,编程同样需要大量的创造力。或许你曾经遇到过类似的事情,你在睡梦中找到了问题的解决方案。这是因为你的右脑处理问题的方式很不同,它可以从各种地方获得信息。敏捷开发权威人士Andy Hunt就这个话题写了一本书《程序员的思维修炼》。如果你想点燃你的每一个神经元,建议你开始学习一门交叉的技能。

不害怕探索陌生程序语言

接触新专案或是转换工作跑道时,都有可能需要学习全然陌生的程序语言,许多人对此感到害怕,甚至未尝试就先放弃。其中,跳脱舒适圈的恐惧往往多于学习程序,会担心是否无法重现过去工作的好表现,甚至因此怀疑自身能力。

不论是多厉害的工程师,一定都有起点,就像打造Microsoft Windows基础的微软资深工程师Dave Cutler为文组出身,没受过正式电脑科学教育,比起同辈花更多时间在错误中学习。

在这之中,最重要的两个关键为具备「成长心态」(growth-mindset)而非「固守心态」(fixed-mindset),以及「乐于学习」(optimize for learning)的态度。

学习陌生程序语言这项关键能力会越练越上手,并让你在学习过程中成为更好的程序设计师。

精通Debug

为什麽程序跑出来和我预期的不一样?
是许多工程师会遇到的问题。Debug能力往往是影响工程师是否能顺利完成专案的关键因素,却被大部分人低估。

Debug的系统性思考如下:

  • 先假设造成bug的可能原因。
  • 若假设为真,界定此假设可能导致的结果。
  • 试著检视是否有和这些结果衝突的现象。
  • 若有衝突表示假设错误,要重複上述思考过程。

由此可知,想加快Debug速度,要提升「提出假设」和「检视假设」的能力。假设能力可随著Debug经验的累积而提升,检视能力则需加强善用检测工具的技能。

在此过程,必须先假设所有东西都是可检视的,并找出可用来检测或加快检测速度的工具或机制,千万不要只用自己熟悉的工具。

开发节省时间的工具

减少时间做那些电脑就可做的工作,例如开发节省时间的工具和使工作流程自动化。

曾负责Facebook软件基础建设团队的软件工程师Bobby Johnson,带领该团队从6人成长至超过1百人。他观察到,团队中表现出色的人多数写了许多工具,这些看似和绩效无直接相关的工具开发时间可能佔三分之一的工作时间,却因此大大提升工作效率,其中包含用来部署程序、监测系统,以及其他可节省时间的工具。

优化重复性工作的速度

软件工程师每天可能要搜寻、浏览函数定义很多次,善用键盘快捷键可省下可观的时间。

例如,每次搜寻需花12秒,类似的步骤每天要重複20次,若用快捷键可将搜寻时间缩短到2秒,一年下来即省了40个小时。其他状况如每次Debug都需要在不同装置测试,除了要分别打开app,还要设定测试情境,这时候就可以思考如何加快这类重複性工作的速度。

发展系统性思考模式

写完程序码、让程序可运作仅是冰山一角,要产出真正有价值的程序,必须从程序本身提升到整个系统来思考。

  • 你的程序和其他程序库以及其他人写的功能是否相容?
  • 程序是否测试完成,并确保其他成员可执行你写的这些功能?
  • 部署你的程序需要改变哪些生产环境?
  • 新程序对其他正在运作的系统是否有负面影响?
  • 客户和使用者的新程序使用情况是否如预期?
  • 新程序是否达到公司期待的效果?

固定型思维模式改变的四个方法。

对称赞和成功进行认知转换

第一,对称赞和成功进行认知转换。转换对称赞的认知,我的意思是当你获得错误方式的称赞时,将它们转换为有利成长型思维模式的称赞。因此如果有人说“哇,你的工作做得真好,你太聪明了!”,你可以将它转换为“耶!太好了,我在这个项目中真努力!”。你没必要大声地喊出来!但是认知转换能让你提高寻求挑战和付出努力的主动性!

你可以在成功或成就中采用相同的方式。当一些事情进行的顺利的时候,不要觉得“当然会做的很好因为我聪明啊”,而是想“我在这个项目中采用了一个有效的方法!我应该更多地去应用这个方法”。

转换对失败的认知

第二,转换对失败的认知。当然这个方法的另一面也非常有效。固定型思维模式和成长型思维模式的很大一部分是你怎样应对失败。当你面对挫折或者没有得到你想要的结果时,你的内心戏是怎么样的?如果你觉得“可能我确实不适合这份工作”,这时应该用红色小旗做标识。与此相反,你应该问问你从你的失败中得到了什么或者哪种学习方式你需要改变。这个方法听起来很平常,但是真的很有用。

为挑战庆幸

第三,为挑战庆幸。当你必须竞争的时候你是什么样的反应?试着为此感到庆幸。这是我在Recurse Center工作时始终坚持的习惯。一些人会坐在我旁边说:“我遇到一个奇葩的Python bug(叹气)”。 我说:“太好了,我就喜欢奇葩的python bugs!”。首先,让我们来说说,有一点是清楚的——当你遇到一个奇葩的bug,相对于bug本身更重要的是,这说明你找到了一些可以通过努力获得成就感的事情,这些事情是你可遇不可求的。

像我提到的一样,在Recurse Center没有交付日期,没有任务分配,因此这种心态是无需付出任何代价的。我一般会说“你可以花一天时间在Flask(python的一个框架)上追踪这个bug,多好啊!”现在,在Dropbox(一种云存储服务)上,我们有一个产品要开发,有交付日期和相应用户。我不能总是一味地为花一天时间来为追踪bug感到高兴。因此,我对身处有交付日期的现实中的人们深感同情。然而,如果我必须修复一个漏洞,我承认bug的存在不利于我对漏洞的修复。但是在没有交付日期的情况下,你仍然可以采用我的态度。

关注过程

第四,关注过程。跟很多人一样,我同一些优秀的工程师一起工作。有时,我会试着用不合理的方式修复一些棘手的bug,但是有些人能够以正确的方式修复。在这种情况下,我会习惯性地问他们怎么做到的。尤其当我刚用Dropbox的时候,他们的回答会很有启发性。有时,他们回答的一些信息来自于我根本不知道的知识中。现在,我在这里待得久了,经常看到和别人技术和方法上的不同,或者发现一些自己的方式之所以不能成功的细节。

这种方法对于总是觉得:“这个人能解决这个bug一定是个天才!”的一类人,是长期最有效的。

总结

掌握一门新技术振奋人心,这是一项影响你思维的新的体验。但是首先,你必须克服你的惯性,一旦你做到了,你便开启了从web的每个角落学习知识的旅程。我希望上面讲的十点能够给你的旅程带来一些帮助或启发。

]]>
- - + + 方法论 + +
+ + 关于Linux问题的解决办法 + /posts/cf0c10bf/ +

关于Linux问题的解决办法

+

我安装win10和Debian系的linux双系统,以这个双系统为基础,解决linux问题。

+
+

关于win10更新之后,重新启动没有windows的引导的问题

解决方法:

+
    +
  • 进入Linux操作系统,打开命令行

    +
  • +
  • 输入 su 切换root用户

    +
  • +
  • 输入
    apt-get update
    update-grub

    +
  • +
  • 重启系统,出现windows的引导

    +
  • +
+ +

关于当前使用用户不在sudoers文件中,无法使用sudo命令的问题

解决方法:

+
    +
  • 切换到超级用户root su

    +
  • +
  • 查看/etc/sudoers权限,可以看到当前权限为440
    ls -all /etc/sudoers
    出现下列:
    -r–r—– 1 root root 744 6月 8 10:29 /etc/sudoers

    +
  • +
  • 更改权限为777
    chmod 777 /etc/sudoers

    +
  • +
  • 编辑/etc/sudoers
    vi /etc/sudoers

    +
  • +
  • root ALL=(ALL:ALL) ALL 下面添加一行
    user ALL=(ALL)ALL
    然后保存退出。

    +

    解释:第一个ALL是指网络中的主机,我们后面把它改成了主机名,它指明user可以在此主机上执行后面的命令。第二个括号里的ALL是指目标用户,也就是以谁的身份去执行命令。最后一个ALL当然就是指命令名了。

    +
  • +
  • 把/etc/sudoers权限改回440
    chmod 440 /etc/sudoers

    +
  • +
  • 操作完成,可以使用sudo命令

    +
  • +
+

Linux中GRUB引导故障的修复

解决方法:

+
    +
  • 需要用usb做个Debian的系统安装盘

    +
  • +
  • 从usb启动,进入debian的修复模式,进入终端

    +
  • +
  • fdisk -l 查看分区情况

    +
  • +
  • 需要识别出分区与原文件系统的挂接关系
    /dev/sda7 swp
    /dev/sda8 /
    /dev/sda9 /home
    /dev/sda10 /boot

    +
  • +
  • 把与目录/对应的分区/dev/sda8挂在/mnt上,把与目录home对应的分区/dev/sda9挂在/mnt/home上,
    把/dev挂在/mnt/dev上

    +
  • +
  • 输入命令chroot /mnt

    +
  • +
  • 输入命令grub-install /dev/sda

    +
  • +
  • 重启,出现引导

    +
  • +
  • 进入系统,
    su
    update-grub

    +
  • +
  • 重启,进入系统

    +
  • +
+]]>
- - 方法论 - + Linux - - - - - 方法论 - - - -
- - - - - 关于Linux问题的解决办法 - - /posts/cf0c10bf/ - -

关于Linux问题的解决办法

我安装win10和Debian系的linux双系统,以这个双系统为基础,解决linux问题。

关于win10更新之后,重新启动没有windows的引导的问题

解决方法:

  • 进入Linux操作系统,打开命令行

  • 输入 su 切换root用户

  • 输入
    apt-get update
    update-grub

  • 重启系统,出现windows的引导

关于当前使用用户不在sudoers文件中,无法使用sudo命令的问题

解决方法:

  • 切换到超级用户root su

  • 查看/etc/sudoers权限,可以看到当前权限为440
    ls -all /etc/sudoers
    出现下列:
    -r–r—– 1 root root 744 6月 8 10:29 /etc/sudoers

  • 更改权限为777
    chmod 777 /etc/sudoers

  • 编辑/etc/sudoers
    vi /etc/sudoers

  • root ALL=(ALL:ALL) ALL 下面添加一行
    user ALL=(ALL)ALL
    然后保存退出。

    解释:第一个ALL是指网络中的主机,我们后面把它改成了主机名,它指明user可以在此主机上执行后面的命令。第二个括号里的ALL是指目标用户,也就是以谁的身份去执行命令。最后一个ALL当然就是指命令名了。

  • 把/etc/sudoers权限改回440
    chmod 440 /etc/sudoers

  • 操作完成,可以使用sudo命令

Linux中GRUB引导故障的修复

解决方法:

  • 需要用usb做个Debian的系统安装盘

  • 从usb启动,进入debian的修复模式,进入终端

  • fdisk -l 查看分区情况

  • 需要识别出分区与原文件系统的挂接关系
    /dev/sda7 swp
    /dev/sda8 /
    /dev/sda9 /home
    /dev/sda10 /boot

  • 把与目录/对应的分区/dev/sda8挂在/mnt上,把与目录home对应的分区/dev/sda9挂在/mnt/home上,
    把/dev挂在/mnt/dev上

  • 输入命令chroot /mnt

  • 输入命令grub-install /dev/sda

  • 重启,出现引导

  • 进入系统,
    su
    update-grub

  • 重启,进入系统

]]>
- - + + Linux + +
+ + 格局 + /posts/e913391a/ +

格局

格局就是指一个人的眼光、胸襟、胆识、心理等要素的内在布局。

+

如果把人生当做一盘棋,那么人生的结局就由这盘棋的格局决定。想要赢得人生这盘棋的胜利,关键在于把握住棋局。

+

一个人的格局大小与否说实话是很难定义的,但是一个人是否拥有广阔胸襟却对自己以及周围的人影响很大。

+

胸怀的大小会让你看见不一样的世界,会让你寻找到生活中旁人看不到的风景。

+

你是什么样的人,你就会和什么样的人交朋友,这句话还是很有道理的。

+ +

做人智商高不高没关系,情商高不高也问题不大,但做人的格局一定要大,说白了,你可以不聪明,也可以不懂交际,但一定要大气。

+

“再大的烙饼也大不过烙它的锅。”你可以烙出大饼来,但是你烙出的饼再大,它也得受烙它的那口锅的限制。

+

我们所希望的未来就好像这张大饼一样,是否能烙出满意的“大饼”,完全取决于烙它的那口“锅”。

+

这就是所谓的“格局”。

+

有一个乞丐,整天在街上乞讨,对路上衣着光鲜的人毫无感觉,却嫉妒比自己乞讨得多的乞丐,这人估计一直就是个乞丐了。

+

一个人的发展往往受局限,其实“局限”就是格局太小,为其所限。谋大事者必要布大局,对于人生这盘棋来说,我们首先要学习的不是技巧,而是布局。

+

大格局,即以大视角切入人生,力求站得更高、看得更远、做得更大。大格局决定着事情发展的方向,掌控了大格局,也就掌控了局势。

+

为什么别人会有大格局?

有的人说,站的高才能看的远;也有人说,欲为大树,莫于草争;有人说,格局即大局观了;有人说,大格局就是大胸怀;还有人说,大格局就是看的远。

+

不过,事物也本无对错之分。站的高,确实是能够看的远。有大格局的人确实也不会斤斤计较,有大格局的也往往看的远。

+

很多人认为,后天的成就主要靠自己。虽说,一个人是否有作为,后天的努力占了很大的部分。但是,先天性的环境因素占了很大一部分。

+

试想,如果你从小生活在一个资源匮乏的环境,眼界往往不够开阔,总是为基本的生活而操劳,哪来格局。但是,即便是有的人生活在资源充沛的环境,也见过大世面,也并不一定有大格局。但是,可以肯定的是格局受环境影响很大。而我们大部分人,其实总体生活的环境本质差异并非太大。

+

眼光

+

眼光是指在某一时刻,对某领域趋势准确预测的能力。

+
+
    +
  • 第一,你能不能看到别人看不到的东西,能不能够透过表象看到事物发展的本质。
  • +
  • 第二,对于事物的评判已经有自己的标准,并能够极为准确根据现在对未来进行预测。
  • +
  • 第三,是你知道这些道理之后,自己能不能做得到。
  • +
+

人贵有自知之明,知道什么可为和不可为。若不可为,怎样做才能可为,那何时可为。

+

胸襟

人的胸怀很有意思,有大的追求,大的愿望,就会有大的忍耐,大的包容,大的视野,大的宽容,这就叫大胸怀吧。

+

如果你的想法是追求一个具体的、很小的事情,你得不到它会很生气;如果你想要的是别人没有的,是很大的东西,很远的东西,你就会变得能够理解很多,包容很多,能够承受痛苦,甚至伤害你的事情你也能够包容。这是一个正循环。

+

如果一点点挫折就让你爬不起来,如果一两句坏话、就让你不能释怀,如果动不动就讨厌人,憎恨人,那格局就太小了。

+

做人有多大气,就会有多成功。因为胸襟,才是成功者的标志。

+

胆识

曾有企业家这样说,“如果是现在把我归零,我仍然可以再来一次”。然而,史玉柱则是在资产为负数,甚至负得还很多的时候站了起来。

+

应该说,他是中国迄今为止唯一经历了“大起——大落——又大起”这样一个完整过程的著名企业家,他创造了一个中国乃至全球经济史上绝无仅有的传奇故事。

+

当巨人大厦倒塌,讨债人蜂拥而至之时,史玉柱庄重承诺:“欠老百姓的钱一定要还。”也正是出于这种“还债”的动力,史玉柱终于东山再起,且赚钱后的第一件事情就是还债。

+

行军作战需要胆识,成功创业更需要胆识,只有想法却不敢去实现终究不会成功,莽撞行事也只会导致失败,有勇有谋才能事半功倍。

+

总结

拥有大格局者:

+
    +
  • 有开阔的心胸
  • +
  • 没有因环境的不利而妄自菲薄
  • +
  • 更没有因为能力的不足而自暴自弃。
  • +
+

拥有小格局者:

+
    +
  • 往往会因为生活的不如意而怨天尤人
  • +
  • 因为一点小的挫折就一筹莫展
  • +
  • 看待问题的时候常常是一叶障目不见泰山,成为碌碌无为的人。局不够大,人生成就再高也有限!
  • +
+

所以说,格局真的决定人生层次。

+
    +
  • 格局在岳飞那里就是八千里路云和月,三千功名尘与土的壮烈;
  • +
  • 格局在马致远那里却是小桥流水人家,断肠人在天涯的孤旅;
  • +
  • 格局在苏轼那里就是我欲乘风归去,又恐琼楼玉宇,高处不胜寒的的寂寞;
  • +
  • 格局在柳永那里就是杨柳岸,晓风残月,衣带渐宽终不悔,为伊消得人憔悴的烟花柳巷而已。
  • +
+

一个人有多大的格局才有多大的胸襟。格局是一种眼界,是一种大情怀,海纳百川才能有容乃大。

+

什么样的眼界和胸襟才能看到更远的风景,站在高处,整座城市不过就是几座楼房,在飞机上从云端俯瞰城市,城市也就变成了盆景。

+

放下你的浮躁,放下你的懒惰,放下你的三分钟热度,放空你禁不住诱惑的大脑,放开你容易被任何事物吸引的眼睛,放淡你什么都想聊两句八卦的嘴巴,静下心来好好做你该做的事,该好好努力了!有时候真的努力后,你会发现自己要比想象的优秀很多。

+

世上除了生死,其它都是小事。不管遇到了什么烦心事,都不要自己为难自己;无论今天发生多么糟糕的事,都不要对生活失望,因为还有明天。   

+
    +
  • 有目标的人在奔跑,没目标的人在流浪,因为不知道要去哪里!

    +
  • +
  • 有目标的人在感恩,没目标的人在报怨,因为觉得全世界都欠他的!

    +
  • +
  • 有目标的人睡不着,没目标的人睡不醒,因为不知道起来去干嘛!

    +
  • +
+

生命只有走出来的精彩,没有等待出来的辉煌!  

+
    +
  • 如果,感到此时的自己很辛苦,那告诉自己:容易走的都是下坡路!坚持住,因为你正在走上坡路,走过去,你就一定会有进步。

    +
  • +
  • 如果,你正在埋怨命运不眷顾,那请记住:命,是失败者的借口;运,是成功者的谦词。命虽由天定,但埋怨,只是一种懦弱的表现;努力,才是人生的态度!相信你可以!

    +
  • +
+

记住一句话:越努力,越幸运。

+]]>
- - Linux - + 方法论 - - - - - Linux - - - -
- - - - - 格局 - - /posts/e913391a/ - -

格局

格局就是指一个人的眼光、胸襟、胆识、心理等要素的内在布局。

如果把人生当做一盘棋,那么人生的结局就由这盘棋的格局决定。想要赢得人生这盘棋的胜利,关键在于把握住棋局。

一个人的格局大小与否说实话是很难定义的,但是一个人是否拥有广阔胸襟却对自己以及周围的人影响很大。

胸怀的大小会让你看见不一样的世界,会让你寻找到生活中旁人看不到的风景。

你是什么样的人,你就会和什么样的人交朋友,这句话还是很有道理的。

做人智商高不高没关系,情商高不高也问题不大,但做人的格局一定要大,说白了,你可以不聪明,也可以不懂交际,但一定要大气。

“再大的烙饼也大不过烙它的锅。”你可以烙出大饼来,但是你烙出的饼再大,它也得受烙它的那口锅的限制。

我们所希望的未来就好像这张大饼一样,是否能烙出满意的“大饼”,完全取决于烙它的那口“锅”。

这就是所谓的“格局”。

有一个乞丐,整天在街上乞讨,对路上衣着光鲜的人毫无感觉,却嫉妒比自己乞讨得多的乞丐,这人估计一直就是个乞丐了。

一个人的发展往往受局限,其实“局限”就是格局太小,为其所限。谋大事者必要布大局,对于人生这盘棋来说,我们首先要学习的不是技巧,而是布局。

大格局,即以大视角切入人生,力求站得更高、看得更远、做得更大。大格局决定着事情发展的方向,掌控了大格局,也就掌控了局势。

为什么别人会有大格局?

有的人说,站的高才能看的远;也有人说,欲为大树,莫于草争;有人说,格局即大局观了;有人说,大格局就是大胸怀;还有人说,大格局就是看的远。

不过,事物也本无对错之分。站的高,确实是能够看的远。有大格局的人确实也不会斤斤计较,有大格局的也往往看的远。

很多人认为,后天的成就主要靠自己。虽说,一个人是否有作为,后天的努力占了很大的部分。但是,先天性的环境因素占了很大一部分。

试想,如果你从小生活在一个资源匮乏的环境,眼界往往不够开阔,总是为基本的生活而操劳,哪来格局。但是,即便是有的人生活在资源充沛的环境,也见过大世面,也并不一定有大格局。但是,可以肯定的是格局受环境影响很大。而我们大部分人,其实总体生活的环境本质差异并非太大。

眼光

眼光是指在某一时刻,对某领域趋势准确预测的能力。

  • 第一,你能不能看到别人看不到的东西,能不能够透过表象看到事物发展的本质。
  • 第二,对于事物的评判已经有自己的标准,并能够极为准确根据现在对未来进行预测。
  • 第三,是你知道这些道理之后,自己能不能做得到。

人贵有自知之明,知道什么可为和不可为。若不可为,怎样做才能可为,那何时可为。

胸襟

人的胸怀很有意思,有大的追求,大的愿望,就会有大的忍耐,大的包容,大的视野,大的宽容,这就叫大胸怀吧。

如果你的想法是追求一个具体的、很小的事情,你得不到它会很生气;如果你想要的是别人没有的,是很大的东西,很远的东西,你就会变得能够理解很多,包容很多,能够承受痛苦,甚至伤害你的事情你也能够包容。这是一个正循环。

如果一点点挫折就让你爬不起来,如果一两句坏话、就让你不能释怀,如果动不动就讨厌人,憎恨人,那格局就太小了。

做人有多大气,就会有多成功。因为胸襟,才是成功者的标志。

胆识

曾有企业家这样说,“如果是现在把我归零,我仍然可以再来一次”。然而,史玉柱则是在资产为负数,甚至负得还很多的时候站了起来。

应该说,他是中国迄今为止唯一经历了“大起——大落——又大起”这样一个完整过程的著名企业家,他创造了一个中国乃至全球经济史上绝无仅有的传奇故事。

当巨人大厦倒塌,讨债人蜂拥而至之时,史玉柱庄重承诺:“欠老百姓的钱一定要还。”也正是出于这种“还债”的动力,史玉柱终于东山再起,且赚钱后的第一件事情就是还债。

行军作战需要胆识,成功创业更需要胆识,只有想法却不敢去实现终究不会成功,莽撞行事也只会导致失败,有勇有谋才能事半功倍。

总结

拥有大格局者:

  • 有开阔的心胸
  • 没有因环境的不利而妄自菲薄
  • 更没有因为能力的不足而自暴自弃。

拥有小格局者:

  • 往往会因为生活的不如意而怨天尤人
  • 因为一点小的挫折就一筹莫展
  • 看待问题的时候常常是一叶障目不见泰山,成为碌碌无为的人。局不够大,人生成就再高也有限!

所以说,格局真的决定人生层次。

  • 格局在岳飞那里就是八千里路云和月,三千功名尘与土的壮烈;
  • 格局在马致远那里却是小桥流水人家,断肠人在天涯的孤旅;
  • 格局在苏轼那里就是我欲乘风归去,又恐琼楼玉宇,高处不胜寒的的寂寞;
  • 格局在柳永那里就是杨柳岸,晓风残月,衣带渐宽终不悔,为伊消得人憔悴的烟花柳巷而已。

一个人有多大的格局才有多大的胸襟。格局是一种眼界,是一种大情怀,海纳百川才能有容乃大。

什么样的眼界和胸襟才能看到更远的风景,站在高处,整座城市不过就是几座楼房,在飞机上从云端俯瞰城市,城市也就变成了盆景。

放下你的浮躁,放下你的懒惰,放下你的三分钟热度,放空你禁不住诱惑的大脑,放开你容易被任何事物吸引的眼睛,放淡你什么都想聊两句八卦的嘴巴,静下心来好好做你该做的事,该好好努力了!有时候真的努力后,你会发现自己要比想象的优秀很多。

世上除了生死,其它都是小事。不管遇到了什么烦心事,都不要自己为难自己;无论今天发生多么糟糕的事,都不要对生活失望,因为还有明天。   

  • 有目标的人在奔跑,没目标的人在流浪,因为不知道要去哪里!

  • 有目标的人在感恩,没目标的人在报怨,因为觉得全世界都欠他的!

  • 有目标的人睡不着,没目标的人睡不醒,因为不知道起来去干嘛!

生命只有走出来的精彩,没有等待出来的辉煌!  

  • 如果,感到此时的自己很辛苦,那告诉自己:容易走的都是下坡路!坚持住,因为你正在走上坡路,走过去,你就一定会有进步。

  • 如果,你正在埋怨命运不眷顾,那请记住:命,是失败者的借口;运,是成功者的谦词。命虽由天定,但埋怨,只是一种懦弱的表现;努力,才是人生的态度!相信你可以!

记住一句话:越努力,越幸运。

]]>
- - + + 方法论 + +
+ + 用GitHub和hexo搭建个人主站 + /posts/a79c8cf7/ +

用GitHub和hexo搭建个人主站

前言

作为一个程序员,拥有一个自己的博客,平时记录一下,分享点技术文章,是很有必要的。建立博客的通常渠道包括:

+
    +
  1. 在博客平台上注册,比如 博客园、CSDN、新浪博客 等。
  2. +
  3. 利用博客框架搭建,如 WordPress、Jekyll、hexo 等。
  4. +
  5. 自己用代码写一个。
  6. +
+

其中,第一种最简单,也最受限,说不定还会被删帖删号。第二种稍复杂,另外需要自己找部署的服务器,但可定制化较高,是很多程序员的选择。最后一种,是在重复造轮子,不过从另一个方面来看,倒是锻炼编程能力的好方式。

+

下面我们就来看下第二种搭建博客的方式:

+
    +
  1. github+hexo 建立你的第一个博客
  2. +
  3. 部署博客及更新博文
  4. +
  5. 安装自己喜欢的主题
  6. +
  7. 购买并绑定域名
  8. +
+ +

第一步:github+hexo 建立你的第一个博客

下面先介绍为何选择 GitHubPages 和 Hexo 来搭建博客,然后介绍搭建博客的详细过程。

+

Why GitHub Pages and Hexo

+

因为 GitHub 的存在,我们得以简单快速地搭建个人博客。

+

GitHub,是一个代码托管网站和社交编程网站。这里聚集了世界上各路技术牛叉的大牛,和最优秀的代码库。

+

GitHub Pages,是用来托管 GitHub 上静态网页的免费站点,那 GitHub Pages具体有哪些功能呢:

+
    +
  • 有 300M 免费空间,资料自己管理,保存可靠;
  • +
  • 享受 GitHub 的便利,上面有很多大牛,眼界会开阔很多;
  • +
  • 可以使用很多现成的博客框架,搭建过程简单快速。
  • +
+

Hexo 是一个简单、快速、强大的静态博客框架,出自台湾大学生 tommy351 之手。我也试过使用 Jekyll搭建个人博客的过程,确实要繁琐许多。相比之下 Hexo 更轻便更快捷,下面是其官网强调的四大特点:

+
    +
  • 极速生成静态页面
  • +
  • 一键部署博客
  • +
  • 丰富的插件支持
  • +
  • 支持 Markdown
  • +
+

大家对 GitHub Pages 和 Hexo 有了一定的了解,下面进入正题。

+

创建 GitHub Pages 仓库

注册 GitHub

访问 GitHub,注册十分简单,一定要记住注册时使用的邮箱,因为 GitHub 上很多通知都是通过邮箱的。申请成功后,在 GitHub 官网上登录,并验证邮箱即可。

+

在 GitHub 上建立仓库

与 GitHub 建立好连接之后,就可以方便的使用它提供的 Pages 服务,GitHub Pages 分两种,一种是用你的 GitHub 用户名建立的 username.github.io 这样的用户&组织站点,另一种是依附项目的 Pages。

+

想建立个人博客是用的第一种,形如 【username.github.io】 这样的可访问的站点,每个用户名下面只能建立一个。建立仓库的方法参照github官网的教程。

+

搭建HEXO所需环境

安装软件

Node.js下载完成后根据提示一步一步安装就好,这个没有什么需要特别说明的。

+

GitHub for Windows下载并安装这个软件,一直点击下一步即可

+

git

+

使用GitHub for Windows登录GitHub

配置 SSH

+

我们如何让本地 git 项目与远程的 GitHub 建立联系呢?方法是用 SSH。

+

打开命令行,输入以下命令:ssh -T git@github.com

+

如果是下面之类的反馈(或者显示 Hi xxx):
The authenticity of host 'github.com ' can't be established. RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48. Are you sure you want to continue connecting (yes/no)?
不用紧张,输入 yes 之后就配置成功了。

+

Hexo 安装

Node和Git都安装好后,首先创建一个文件夹,如blog,用户存放hexo的配置文件,然后进入blog里安装Hexo。

+

打开git bash命令行,输入命令:npm install -g hexo

+

创建 Hexo 博客

Hexo 初始化

Hexo 的初始化命令:hexo init

+

部署成功之后,用hexo生成静态页面,输入命令:hexo generate或者hexo g也可以

+

此时在本地进行预览(在刚才创建的blog文件夹里),输入命令:hexo server或者hexo s

+

此时打开浏览器,在浏览器地址栏输入 http://localhost:4000/ (默认端口为4000), 便可以看到最原始的博客了。

+

以后发表博文想先预览,也可以通过 hexo server 在本地先跑起来,看看效果。

+

在 Git Shell 中按 Ctrl+c 可以停止该服务。

+

配置Github

建立Repository:建立与你用户名对应的仓库,仓库名必须为【username.github.io】,这是固定写法

+

然后建立关系,找到之前建立的blog文件夹,之前建的东西也全在这里面,有:

+
_config.yml    node_modules    public      source
+db.json        package.json    scaffolds  themes
+

现在我们需要修改_config.yml文件,来建立关联,使用notepad++打开_config.yml文件

+

翻到最下面,改成这样:

+
deploy:
+    type: git
+    repo: https://github.com/username/username.github.io.git
+    branch: master
+

注:username为你的用户名

+

然后执行命令:npm install hexo-deployer-git --save

+

然后,执行配置命令:hexo deploy

+

然后在浏览器中输入http://username.github.io/ 就行了。

+

部署步骤

每次部署的步骤,可按以下三步来进行:

+
`hexo clean`
+`hexo generate`
+`hexo deploy`
+

报错总结

问题1:

+
ERROR Deployer not found: git 或者 ERROR Deployer not found: github
+

解决方法:npm install hexo-deployer-git --save

+

问题2:

+
如发生报错: ERROR Process failed: layout/.DS_Store
+

那么进入主题里面layout和_partial目录下,使用删除命令:rm-rf.DS_Store

+

问题3:

+
ERROR Plugin load failed: hexo-server
+原因:
+Besides,utilities are separated into a standalone module.hexo.util is not reachable anymore.
+

解决方法:npm install hexo-server

+

问题4:

+
执行命令hexo server,提示:Usage: hexo ....
+原因:
+我认为是没有生成本地服务
+

解决方法:npm install hexo-server --save

+

问题5:

+
提示:hexo-server@0.1.2 node_modules/hexo-server
+....
+表示成功了参考
+

这个时候再执行:hexo-server

+
得到:
+INFOHexois running at http://0.0.0.0:4000/.PressCtrl+C to stop.
+

这个时候再点击http://0.0.0.0:4000,正常情况下应该是最原始的画面。

+

这个时候再重新生成静态文件,命令:hexo generatehexo g

+

启动本地服务器:hexo serverhexo s

+

本地已经简单的设置好了,但是现在域名和服务器都是基于自己的电脑,接下来需要跟github进行关联。

+

第二步:部署博客及更新博文

在blog文件夹下将博客放入public文件夹中

+

在blog文件夹下打开git bash,按以下三步进行:

+
`hexo clean`
+`hexo g`
+`hexo d`
+

第三步:安装主题

我安装的是nexT主题,可参考主题作者在GitHub的READMEnexT

+

还有我比较喜欢的主题 yilia

+

第四步:购买并绑定域名

购买域名

我是在万网上购买的域名,越出名的后缀越贵,看自己吧,比如.com .cn .net这些域名还需要备案,否则用不了。

+

绑定域名

创建CNAME。

+
    +
  1. 登陆访问github。
  2. +
  3. 进入github中需要关联域名的相应项目。
  4. +
  5. 在该项目下创建CNAME,其CNAME内容即是域名
  6. +
+

前往你的DNS服务商

+

进入”新增解析”界面。

+

在万网首页点击【进入会员中心】→ 点击【产品管理】下的【域名解析】→ 进入【域名列表】界面 → 点击域名→ 进入【新增解析】界面。

+

设置域名解析记录。

+

点击【新增解析】;依次填写相应内容。

+

“记录类型”选择A;”主机记录”填写www;”解析线路”选择默认;

+

“记录值”填写github提供的IP地址,192.30.252.153或192.30.252.154;

+

“TTL”默认10分钟,自己可以另行设置也可;

+

最后点击【保存】。

+

验证域名与github关联是否成功。

+

先以github的链接方式访问一次,查看界面;再以域名的方式访问一次,查看界面;两者所查看到的界面是一致。

+

注:若域名不能立即访问,需等待一段时间再访问。当github成功关联到域名后,以github的链接方式进行访问,其会自动转化为域名访问。

+

参考博客

潘柏信的博客

+

百度

+]]>
- - 方法论 - + blog - - - - - 方法论 - - - -
- - - - - 用GitHub和hexo搭建个人主站 - - /posts/a79c8cf7/ - -

用GitHub和hexo搭建个人主站

前言

作为一个程序员,拥有一个自己的博客,平时记录一下,分享点技术文章,是很有必要的。建立博客的通常渠道包括:

  1. 在博客平台上注册,比如 博客园、CSDN、新浪博客 等。
  2. 利用博客框架搭建,如 WordPress、Jekyll、hexo 等。
  3. 自己用代码写一个。

其中,第一种最简单,也最受限,说不定还会被删帖删号。第二种稍复杂,另外需要自己找部署的服务器,但可定制化较高,是很多程序员的选择。最后一种,是在重复造轮子,不过从另一个方面来看,倒是锻炼编程能力的好方式。

下面我们就来看下第二种搭建博客的方式:

  1. github+hexo 建立你的第一个博客
  2. 部署博客及更新博文
  3. 安装自己喜欢的主题
  4. 购买并绑定域名

第一步:github+hexo 建立你的第一个博客

下面先介绍为何选择 GitHubPages 和 Hexo 来搭建博客,然后介绍搭建博客的详细过程。

Why GitHub Pages and Hexo

因为 GitHub 的存在,我们得以简单快速地搭建个人博客。

GitHub,是一个代码托管网站和社交编程网站。这里聚集了世界上各路技术牛叉的大牛,和最优秀的代码库。

GitHub Pages,是用来托管 GitHub 上静态网页的免费站点,那 GitHub Pages具体有哪些功能呢:

  • 有 300M 免费空间,资料自己管理,保存可靠;
  • 享受 GitHub 的便利,上面有很多大牛,眼界会开阔很多;
  • 可以使用很多现成的博客框架,搭建过程简单快速。

Hexo 是一个简单、快速、强大的静态博客框架,出自台湾大学生 tommy351 之手。我也试过使用 Jekyll搭建个人博客的过程,确实要繁琐许多。相比之下 Hexo 更轻便更快捷,下面是其官网强调的四大特点:

  • 极速生成静态页面
  • 一键部署博客
  • 丰富的插件支持
  • 支持 Markdown

大家对 GitHub Pages 和 Hexo 有了一定的了解,下面进入正题。

创建 GitHub Pages 仓库

注册 GitHub

访问 GitHub,注册十分简单,一定要记住注册时使用的邮箱,因为 GitHub 上很多通知都是通过邮箱的。申请成功后,在 GitHub 官网上登录,并验证邮箱即可。

在 GitHub 上建立仓库

与 GitHub 建立好连接之后,就可以方便的使用它提供的 Pages 服务,GitHub Pages 分两种,一种是用你的 GitHub 用户名建立的 username.github.io 这样的用户&组织站点,另一种是依附项目的 Pages。

想建立个人博客是用的第一种,形如 【username.github.io】 这样的可访问的站点,每个用户名下面只能建立一个。建立仓库的方法参照github官网的教程。

搭建HEXO所需环境

安装软件

Node.js下载完成后根据提示一步一步安装就好,这个没有什么需要特别说明的。

GitHub for Windows下载并安装这个软件,一直点击下一步即可

git

使用GitHub for Windows登录GitHub

配置 SSH

我们如何让本地 git 项目与远程的 GitHub 建立联系呢?方法是用 SSH。

打开命令行,输入以下命令:ssh -T git@github.com

如果是下面之类的反馈(或者显示 Hi xxx):
The authenticity of host 'github.com ' can't be established. RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48. Are you sure you want to continue connecting (yes/no)?
不用紧张,输入 yes 之后就配置成功了。

Hexo 安装

Node和Git都安装好后,首先创建一个文件夹,如blog,用户存放hexo的配置文件,然后进入blog里安装Hexo。

打开git bash命令行,输入命令:npm install -g hexo

创建 Hexo 博客

Hexo 初始化

Hexo 的初始化命令:hexo init

部署成功之后,用hexo生成静态页面,输入命令:hexo generate或者hexo g也可以

此时在本地进行预览(在刚才创建的blog文件夹里),输入命令:hexo server或者hexo s

此时打开浏览器,在浏览器地址栏输入 http://localhost:4000/ (默认端口为4000), 便可以看到最原始的博客了。

以后发表博文想先预览,也可以通过 hexo server 在本地先跑起来,看看效果。

在 Git Shell 中按 Ctrl+c 可以停止该服务。

配置Github

建立Repository:建立与你用户名对应的仓库,仓库名必须为【username.github.io】,这是固定写法

然后建立关系,找到之前建立的blog文件夹,之前建的东西也全在这里面,有:

_config.yml    node_modules    public      sourcedb.json        package.json    scaffolds  themes

现在我们需要修改_config.yml文件,来建立关联,使用notepad++打开_config.yml文件

翻到最下面,改成这样:

deploy:    type: git    repo: https://github.com/username/username.github.io.git    branch: master

注:username为你的用户名

然后执行命令:npm install hexo-deployer-git --save

然后,执行配置命令:hexo deploy

然后在浏览器中输入http://username.github.io/ 就行了。

部署步骤

每次部署的步骤,可按以下三步来进行:

`hexo clean``hexo generate``hexo deploy`

报错总结

问题1:

ERROR Deployer not found: git 或者 ERROR Deployer not found: github

解决方法:npm install hexo-deployer-git --save

问题2:

如发生报错: ERROR Process failed: layout/.DS_Store

那么进入主题里面layout和_partial目录下,使用删除命令:rm-rf.DS_Store

问题3:

ERROR Plugin load failed: hexo-server原因:Besides,utilities are separated into a standalone module.hexo.util is not reachable anymore.

解决方法:npm install hexo-server

问题4:

执行命令hexo server,提示:Usage: hexo ....原因:我认为是没有生成本地服务

解决方法:npm install hexo-server --save

问题5:

提示:hexo-server@0.1.2 node_modules/hexo-server....表示成功了参考

这个时候再执行:hexo-server

得到:INFOHexois running at http://0.0.0.0:4000/.PressCtrl+C to stop.

这个时候再点击http://0.0.0.0:4000,正常情况下应该是最原始的画面。

这个时候再重新生成静态文件,命令:hexo generatehexo g

启动本地服务器:hexo serverhexo s

本地已经简单的设置好了,但是现在域名和服务器都是基于自己的电脑,接下来需要跟github进行关联。

第二步:部署博客及更新博文

在blog文件夹下将博客放入public文件夹中

在blog文件夹下打开git bash,按以下三步进行:

`hexo clean``hexo g``hexo d`

第三步:安装主题

我安装的是nexT主题,可参考主题作者在GitHub的READMEnexT

还有我比较喜欢的主题 yilia

第四步:购买并绑定域名

购买域名

我是在万网上购买的域名,越出名的后缀越贵,看自己吧,比如.com .cn .net这些域名还需要备案,否则用不了。

绑定域名

创建CNAME。

  1. 登陆访问github。
  2. 进入github中需要关联域名的相应项目。
  3. 在该项目下创建CNAME,其CNAME内容即是域名

前往你的DNS服务商

进入”新增解析”界面。

在万网首页点击【进入会员中心】→ 点击【产品管理】下的【域名解析】→ 进入【域名列表】界面 → 点击域名→ 进入【新增解析】界面。

设置域名解析记录。

点击【新增解析】;依次填写相应内容。

“记录类型”选择A;”主机记录”填写www;”解析线路”选择默认;

“记录值”填写github提供的IP地址,192.30.252.153或192.30.252.154;

“TTL”默认10分钟,自己可以另行设置也可;

最后点击【保存】。

验证域名与github关联是否成功。

先以github的链接方式访问一次,查看界面;再以域名的方式访问一次,查看界面;两者所查看到的界面是一致。

注:若域名不能立即访问,需等待一段时间再访问。当github成功关联到域名后,以github的链接方式进行访问,其会自动转化为域名访问。

参考博客

潘柏信的博客

百度

]]>
- - + + blog + +
+ + Hello World + /posts/4a17b156/ +

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

+ +

Quick Start

Create a new post

$ hexo new "My New Post"
+

More info: Writing

+

Run server

$ hexo server
+

More info: Server

+

Generate static files

$ hexo generate
+

More info: Generating

+

Deploy to remote sites

$ hexo deploy
+

More info: Deployment

+]]>
- - blog - + blog - - - - - blog - - - -
- - - - - Hello World - - /posts/4a17b156/ - -

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

]]>
- - - - - blog - - - - - - - blog - - - -
- - - - + + blog + +
diff --git a/sitemap.xml b/sitemap.xml index 9821ba0d..bade0d39 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1,38 +1,45 @@ + + https://www.awebone.com/posts/75c6e52f/ + + 2020-04-01T01:58:59.099Z + + + https://www.awebone.com/posts/e3c0f347/ - 2020-03-31T15:19:08.633Z + 2020-03-31T15:20:38.547Z https://www.awebone.com/posts/dd22b276/ - 2020-03-31T15:18:39.751Z + 2020-03-31T15:20:38.546Z - https://www.awebone.com/posts/e913391a/ + https://www.awebone.com/posts/1d6a9c79/ - 2020-03-31T13:42:45.765Z + 2020-03-31T15:20:38.545Z - https://www.awebone.com/posts/6021eb27/ + https://www.awebone.com/posts/e913391a/ - 2020-03-31T13:42:28.370Z + 2020-03-31T13:42:45.765Z - https://www.awebone.com/posts/75c6e52f/ + https://www.awebone.com/posts/6021eb27/ - 2020-03-31T13:42:22.685Z + 2020-03-31T13:42:28.370Z @@ -113,13 +120,6 @@ - - https://www.awebone.com/posts/1d6a9c79/ - - 2020-03-31T13:16:59.545Z - - - https://www.awebone.com/posts/4370e84d/ @@ -169,13 +169,6 @@ - - https://www.awebone.com/posts/800507c2/ - - 2020-03-25T15:38:39.779Z - - - https://www.awebone.com/posts/fd5cbc55/ diff --git a/sw-register.js b/sw-register.js index 5e9e46ae..13b91ce0 100644 --- a/sw-register.js +++ b/sw-register.js @@ -1 +1 @@ -navigator.serviceWorker&&navigator.serviceWorker.register('/sw.js?v=20200331232120').then(function(){navigator.serviceWorker.addEventListener('message',function(a){if('sw.update'===a.data){let a=document.querySelector('meta[name=theme-color]'),b=document.createElement('div');a&&(a.content='#000'),b.innerHTML='
\u70B9\u51FB\u5237\u65B0
',document.body.appendChild(b),setTimeout(function(){document.getElementById('app-refresh').className+=' app-refresh-show'},16)}})}); \ No newline at end of file +navigator.serviceWorker&&navigator.serviceWorker.register('/sw.js?v=20200510222530').then(function(){navigator.serviceWorker.addEventListener('message',function(a){if('sw.update'===a.data){let a=document.querySelector('meta[name=theme-color]'),b=document.createElement('div');a&&(a.content='#000'),b.innerHTML='
\u70B9\u51FB\u5237\u65B0
',document.body.appendChild(b),setTimeout(function(){document.getElementById('app-refresh').className+=' app-refresh-show'},16)}})}); \ No newline at end of file diff --git a/sw.js b/sw.js index ad511ea5..2825202d 100644 --- a/sw.js +++ b/sw.js @@ -10,7 +10,7 @@ 'use strict'; -var precacheConfig = [["/404.html","3a90c1c3aed2b3d23e1f02175cb2d91a"],["/about/index.html","30aa156efe27e6a7864d72c255caa7c1"],["/archives/index.html","a5e99c5a17695a627d31c5f38bd5401f"],["/assets/css/APlayer.min.css","fbe994054426fadb2dff69d824c5c67a"],["/assets/css/DPlayer.min.css","31ac9b1a5a7f018dcc9a0e0f66261c08"],["/assets/js/APlayer.min.js","8f1017e7a73737e631ff95fa51e4e7d7"],["/assets/js/DPlayer.min.js","4097986cff510567068128f4b18004a6"],["/assets/js/Meting.min.js","bfac0368480fd344282ec018d28f173d"],["/baidu_verify_3NWlza1HUZ.html","5363e5c3f451a959c2eff23ab7108f5b"],["/categories/Java/index.html","d2648930afa90186dad6b818f4ac90a9"],["/categories/Linux/index.html","a381d27c092f7a4421e50a2dc54da145"],["/categories/blog/index.html","ae99d2feb505237a739c4c16309fec3a"],["/categories/index.html","c441d3b649c94590c4938f9ad843cba4"],["/categories/web/index.html","0ecdd5090cd68f95e941b537e91f850b"],["/categories/web前端/index.html","66c6d0bde56de46b87a430152752e66f"],["/categories/大数据/index.html","6170b3adb3387ba68faae5f0c71a54e5"],["/categories/工具/index.html","4e950c22d4d8fadc0d8fee1c12574f86"],["/categories/数据库/index.html","560f8f9de5e2de10eadd83b1eb567f64"],["/categories/方法论/index.html","ba206fa07c1faa04ec071ca9f489b843"],["/categories/算法/index.html","65ba7280b7eb34a8de33008cf04dce9a"],["/css/main.css","c4a1585b9d40b570fc56be52007668c7"],["/fonts/ComicNeue-Angular-Bold-Oblique.eot","40788a0a7b51a92389dad8b159492cb8"],["/fonts/ComicNeue-Angular-Bold-Oblique.ttf","7afa6bfc716544b765ad5d7bd61aa390"],["/fonts/ComicNeue-Angular-Bold-Oblique.woff","6c33764ad65ce89edd41147ec0f3541c"],["/fonts/ComicNeue-Angular-Bold-Oblique.woff2","31c870940de1afec23fc652600966664"],["/fonts/ComicNeue-Angular-Bold.eot","97bfd2726c48f293231900ed552e5fd9"],["/fonts/ComicNeue-Angular-Bold.ttf","3b3e96b257325929065b67d0b418b975"],["/fonts/ComicNeue-Angular-Bold.woff","fdfdec9d0b7dfa91fbe11dc2ec50473d"],["/fonts/ComicNeue-Angular-Bold.woff2","c58b01776b2adea50f334750eae72767"],["/fonts/ComicNeue-Angular-Light-Oblique.eot","d6047d25084572d7df4f0de2096b6703"],["/fonts/ComicNeue-Angular-Light-Oblique.ttf","4c9956b9278836ef07a7a806f45b264a"],["/fonts/ComicNeue-Angular-Light-Oblique.woff","4bf616657aa13c10ad173b7b738f2bab"],["/fonts/ComicNeue-Angular-Light-Oblique.woff2","3c074df0239e43a1f33f53483e4bc6bf"],["/fonts/ComicNeue-Angular-Light.eot","008b2822ea0c1c160df2b5ea2991a438"],["/fonts/ComicNeue-Angular-Light.ttf","43c1e8a3968b7fbdc2d98d1ca5dee684"],["/fonts/ComicNeue-Angular-Light.woff","34d7b4224ea5bbd30e4a3fbe8cc8a5e0"],["/fonts/ComicNeue-Angular-Light.woff2","f368a66f957ac4eb4e7f71fbfbbdb101"],["/fonts/ComicNeue-Angular-Regular-Oblique.eot","3e8299e59ae27259e71248832f99786c"],["/fonts/ComicNeue-Angular-Regular-Oblique.ttf","099285f76101ec3291f80cccdca21bdb"],["/fonts/ComicNeue-Angular-Regular-Oblique.woff","00f0e24953b6d6e71ca0891f974bfbdf"],["/fonts/ComicNeue-Angular-Regular-Oblique.woff2","808aab8b0462213b283ab1c0fea3c1d3"],["/fonts/ComicNeue-Angular-Regular.eot","3c6797b44cf639f15d940d5321a49a29"],["/fonts/ComicNeue-Angular-Regular.ttf","96e329b344475cfedef1867f8e002bee"],["/fonts/ComicNeue-Angular-Regular.woff","dec91b007193eb99bfb669e023356495"],["/fonts/ComicNeue-Angular-Regular.woff2","7b8d6bcdc8cb7acdb218aa5e314ac135"],["/fonts/ComicNeue-Bold-Oblique.eot","9623a2602e23e010df808efd573ded50"],["/fonts/ComicNeue-Bold-Oblique.ttf","6a2b4e115cc960db3e5fde8d95e82b6d"],["/fonts/ComicNeue-Bold-Oblique.woff","933e67b18c88f48694adcf02e9340a57"],["/fonts/ComicNeue-Bold-Oblique.woff2","65fd4add501504ffe42281c7c7f0b892"],["/fonts/ComicNeue-Bold.eot","a89b0d636179e835f1038cc1e7b11682"],["/fonts/ComicNeue-Bold.ttf","bb59dfb0d7fa8a0c9b7d431f94ff3d6d"],["/fonts/ComicNeue-Bold.woff","df4f1f0b09e7dcbf110e77a1a5ad936d"],["/fonts/ComicNeue-Bold.woff2","d8a5434f588f9e0f80e095907e6455d0"],["/fonts/ComicNeue-Light-Oblique.eot","3aed4284b4bf38f4ab7709f69a752ae2"],["/fonts/ComicNeue-Light-Oblique.ttf","805069ddfd6bdf57e01089ca90bb866f"],["/fonts/ComicNeue-Light-Oblique.woff","3b44b933104258988d9b125b71ac502f"],["/fonts/ComicNeue-Light-Oblique.woff2","5fcb8adbe863b29fb8f8695aae420e04"],["/fonts/ComicNeue-Light.eot","0e04ebae206c1fe27867e13405072635"],["/fonts/ComicNeue-Light.ttf","27219ea5f3a25dbf3a05903f34ed5bd6"],["/fonts/ComicNeue-Light.woff","780c9f200bbdd3ba13ac9464921ecabf"],["/fonts/ComicNeue-Light.woff2","1b00e4ccf3ff437d92a6958ca0660a73"],["/fonts/ComicNeue-Regular-Oblique.eot","07244e74afacb190403cc2028d56f2ab"],["/fonts/ComicNeue-Regular-Oblique.ttf","b0e3f8f6249f0bb895cd2f96fffee6cd"],["/fonts/ComicNeue-Regular-Oblique.woff","79cbff272c3231694b9d1dd44f8f38fc"],["/fonts/ComicNeue-Regular-Oblique.woff2","00110028a3c3c5fb1e3691d4de42a9ed"],["/fonts/ComicNeue-Regular.eot","3f916f08fa680d8e9ed4d8eaa4614629"],["/fonts/ComicNeue-Regular.ttf","c7823c53863f1386e0154142369242d6"],["/fonts/ComicNeue-Regular.woff","0689422546d69a1a7cffeff379ab42a0"],["/fonts/ComicNeue-Regular.woff2","884ec2a2c477fc7a6681218180011ac1"],["/fonts/font.css","b75a0621de61aaa3198b86ef16dae212"],["/guestbook/index.html","16cb0a5e8e9d4feb096782459687f746"],["/images/QRcode.svg","dbcc882694b4c7e7ea444fcc7b6fc7d4"],["/images/algolia_logo.svg","88450dd56ea1a00ba772424b30b7d34d"],["/images/apple-touch-icon-next.png","fce961f0bd3cd769bf9c605ae6749bc0"],["/images/avatar.gif","2bed513bc5f13733cf9a8a12c4e1a971"],["/images/cc-by-nc-nd.svg","3b009b0d5970d2c4b18e140933547916"],["/images/cc-by-nc-sa.svg","cf2644b7aa5ebd3f5eab55329b4e7cb7"],["/images/cc-by-nc.svg","e63bcae937a1ae4cb6f83d8a1d26893c"],["/images/cc-by-nd.svg","78359b1307baffc2d0e8cffba5dee2dd"],["/images/cc-by-sa.svg","525d2a82716fe9860a65cf0ac5e231a0"],["/images/cc-by.svg","bd656500a74c634b4ff1333008c62cd8"],["/images/cc-zero.svg","2d6242e90c3082e7892cf478be605d26"],["/images/es/es1.png","91fb15e343381b412947734c448c2de5"],["/images/es/es2.png","f985815b4f5c09399973e9e83986c8f6"],["/images/es/es3.png","f0db8ad81237e187bf8306db5bf33e40"],["/images/favicon-16x16-next.png","b8975923a585dbaa8519a6068e364947"],["/images/favicon-32x32-next.png","5a029563fe3214c96f68b46556670ea1"],["/images/h5-audio/1.webAudio-API.jpg","f1e9945bde46ee636eacd129857a5fa7"],["/images/h5-audio/2.AudioContext.jpg","cf62f9e59d6e97663a2c023ce2470f47"],["/images/h5-audio/3.GainNode.jpg","2f2ff1fade2dac6fafc17d9a2119b05c"],["/images/h5-audio/4.AudioBufferSourceNode.jpg","2ca1951f40c770452501e5383bfcffe8"],["/images/h5-audio/5.AnalyserNode.jpg","fdd6b7ba1e84d0b83576bc2216a1582b"],["/images/html-store/H51.jpg","9eb4ba5a95500c05af31d8e4213787f6"],["/images/html-store/H52.jpg","c9c9297860cb29f7669db0e0cf9ba516"],["/images/html-store/IndexedSQL.jpg","f6dd110a59bd9a9dc17cb782b5cf9bec"],["/images/icons/icon-128x128.png","e3b73bed589b8668cfb22689844cad91"],["/images/icons/icon-144x144.png","7d513e9d4c40c932e19003746fb449db"],["/images/icons/icon-152x152.png","041aaec9f001927a2ea2a9f02d266a8a"],["/images/icons/icon-72x72.png","901bddfccbbd720d9ada030274e90289"],["/images/icons/icon-96x96.png","1dce7fa7ee0ad689648b4e094697c317"],["/images/loading.gif","c2196de8ba412c60c22ab491af7b1409"],["/images/logo.svg","88985471c188e5c5a765a8f233c54df5"],["/images/mr-learn/HDFS.png","8dee230ff560ed8a446cdb201bb6776c"],["/images/mr-learn/MR1.png","bc0c135f5a655e2532c5de84d1c416ea"],["/images/mr-learn/MR10.png","5cb62d578f308a9e1cd74e9544714b42"],["/images/mr-learn/MR11.png","17a3469c9a7cf581bf108db879dbb98b"],["/images/mr-learn/MR12.png","40b01a18ab6a7cc7a9ace2a9f5934ced"],["/images/mr-learn/MR13.png","b1e59d1e062c9cb5102f96379cb219c7"],["/images/mr-learn/MR14.png","a9ceb9fe7be41e5d57400206871155da"],["/images/mr-learn/MR2.png","0dd9ae2e313b0b44e827ec2aa5b96522"],["/images/mr-learn/MR3.png","194aa203b5a98b43bea5b7c5935fe7ed"],["/images/mr-learn/MR4.png","cf17816d4bec8d2081cd66b339af4898"],["/images/mr-learn/MR5.png","a58cb9ee79cbad883e0585faa0996759"],["/images/mr-learn/MR6.png","2c642ab26af26511608f4ac6f1ad8691"],["/images/mr-learn/MR7.png","90336274950eaf68e8e709e31eb80a69"],["/images/mr-learn/MR8.png","9768f908cbae4cd0a2ed9a67984b5c3f"],["/images/mr-learn/MR9.png","a6de7726e7f92f7582f07a84b10432ae"],["/images/mr-learn/WordCount.png","0c0a5fc91489244c7beced3d8e135403"],["/images/mysql/base_sql.jpg","8b82bfa1d1f0a49d414fe1bf1c007aad"],["/images/mysql/mysql_char.jpg","9cb9cf51260af18a5bc696d11591c4b2"],["/images/mysql/mysql_data.jpg","646c53e376d5fb4a4d0511b0cfdf2f69"],["/images/mysql/mysql_float.jpg","7c3643254124a8ae456876c6de51e592"],["/images/mysql/mysql_int.jpg","f9088c1ebedee43f5c102c053accc726"],["/images/placeholder.gif","c2196de8ba412c60c22ab491af7b1409"],["/images/quote-l.svg","a9d75107c4d7e31612f98e78be0979f9"],["/images/quote-r.svg","5f902def9e09af7fc41e4cf86ad1a0f9"],["/images/searchicon.png","3d6b5c9d6d6c26a2b76a14b8fdf3438a"],["/images/wechat.svg","2ef3f3696267249c4372a5e3f9db36f2"],["/images/wepay.svg","2e7265f61e62c0ce3af3e4b4713601ca"],["/index.html","bd93e4e057deade34a3e1fe1ee60bc69"],["/js/src/affix.js","683c19859764baf0d17538897ea1eba2"],["/js/src/algolia-search.js","f5fa392318805997089ceb3a925979ba"],["/js/src/bootstrap.js","2a1083772854ae2663748e0a25c17285"],["/js/src/exturl.js","2b444179b3145e5007b4d371dac07cd3"],["/js/src/hook-duoshuo.js","45997b0c06abff3cd88efd901f614065"],["/js/src/js.cookie.js","6e9eb1f53afb135aedaf90739c867738"],["/js/src/motion.js","0f6add86607c451269d0b3d286c84d8b"],["/js/src/post-details.js","b8e8e27c27c697567879c52888ffc24c"],["/js/src/schemes/pisces.js","827b5ad25e1142277c1e7dfe0cacebe5"],["/js/src/scroll-cookie.js","890406ae3539e4721ef5f314542e5e46"],["/js/src/scrollspy.js","fafdd7ab6af233b701506c733910b7f5"],["/js/src/utils.js","24512c3455f976730b7bf75e1222c533"],["/lib/Han/dist/font/han-space.woff","b09f2dd7d3ad8ad07f3b8495133909d9"],["/lib/Han/dist/font/han.woff","e841c6b547bc06a06f60f4de52bf906e"],["/lib/Han/dist/font/han.woff2","2b06aa1c952a2dfaf00d99218689d147"],["/lib/Han/dist/han.css","cfcc552e7aebaef5e2f34aee030b956b"],["/lib/Han/dist/han.js","575b6c1667c01798730fbd972e959c9c"],["/lib/Han/dist/han.min.css","cab466d758269b437167422c4a16b364"],["/lib/Han/dist/han.min.js","96482c9c2b3c5ea9bf5a40db162c7f34"],["/lib/algolia-instant-search/instantsearch.min.css","029a13b44e6807955106ff3c075a02f9"],["/lib/algolia-instant-search/instantsearch.min.js","0db46eba0c8133693ee839507b1612f2"],["/lib/canvas-nest/canvas-nest.min.js","36e103d2a05bc706bac40f9ab8881eb7"],["/lib/canvas-ribbon/canvas-ribbon.js","16dc214240913551986593808c2efcfc"],["/lib/fancybox/source/blank.gif","325472601571f31e1bf00674c368d335"],["/lib/fancybox/source/fancybox_loading.gif","328cc0f6c78211485058d460e80f4fa8"],["/lib/fancybox/source/fancybox_loading@2x.gif","f92938639fa894a0e8ded1c3368abe98"],["/lib/fancybox/source/fancybox_overlay.png","77aeaa52715b898b73c74d68c630330e"],["/lib/fancybox/source/fancybox_sprite.png","783d4031fe50c3d83c960911e1fbc705"],["/lib/fancybox/source/fancybox_sprite@2x.png","ed9970ce22242421e66ff150aa97fe5f"],["/lib/fancybox/source/helpers/fancybox_buttons.png","b448080f8615e664b7788c7003803b59"],["/lib/fancybox/source/helpers/jquery.fancybox-buttons.css","cac75538c2e3ddfadef839feaca8e356"],["/lib/fancybox/source/helpers/jquery.fancybox-buttons.js","f53c246661fb995a3f12e67fa38e0fa0"],["/lib/fancybox/source/helpers/jquery.fancybox-media.js","c017067f48d97ec4a077ccdf056e6a2e"],["/lib/fancybox/source/helpers/jquery.fancybox-thumbs.css","52ddd84a9f42c1d4cd86d518a7f7e8bc"],["/lib/fancybox/source/helpers/jquery.fancybox-thumbs.js","cf1fc1df534eede4cb460c5cbd71aba6"],["/lib/fancybox/source/jquery.fancybox.css","6c55951ce1e3115711f63f99b7501f3a"],["/lib/fancybox/source/jquery.fancybox.js","921e9cb04ad6e2559869ec845c5be39b"],["/lib/fancybox/source/jquery.fancybox.pack.js","cc9e759f24ba773aeef8a131889d3728"],["/lib/fastclick/README.html","b3cd6e7f930bf6e410a2e7eab8a148a8"],["/lib/fastclick/lib/fastclick.js","6e9d3b0da74f2a4a7042b494cdaa7c2e"],["/lib/fastclick/lib/fastclick.min.js","a0fc6c24d1f3ff9ac281887c92b24acd"],["/lib/font-awesome/css/font-awesome.css","c495654869785bc3df60216616814ad1"],["/lib/font-awesome/css/font-awesome.min.css","269550530cc127b6aa5a35925a7de6ce"],["/lib/font-awesome/fonts/fontawesome-webfont.eot","674f50d287a8c48dc19ba404d20fe713"],["/lib/font-awesome/fonts/fontawesome-webfont.svg","acf3dcb7ff752b5296ca23ba2c7c2606"],["/lib/font-awesome/fonts/fontawesome-webfont.ttf","b06871f281fee6b241d60582ae9369b9"],["/lib/font-awesome/fonts/fontawesome-webfont.woff","fee66e712a8a08eef5805a46892932ad"],["/lib/font-awesome/fonts/fontawesome-webfont.woff2","af7ae505a9eed503f8b8e6982036873e"],["/lib/jquery/index.js","32015dd42e9582a80a84736f5d9a44d7"],["/lib/jquery_lazyload/CONTRIBUTING.html","7287727950845c8a1010f3933691afef"],["/lib/jquery_lazyload/README.html","d89aa4afe316331a25b636b5ead4716e"],["/lib/jquery_lazyload/jquery.lazyload.js","8b427f9e86864ee3aaf1ae33e6e14263"],["/lib/jquery_lazyload/jquery.scrollstop.js","f163fd8f02361928853668a96f8a1249"],["/lib/needsharebutton/font-embedded.css","dd8861d10d1ed6b5e0c0011adfb39be9"],["/lib/needsharebutton/needsharebutton.css","30f2f800e13f7b6b83629a4cbd9749ef"],["/lib/needsharebutton/needsharebutton.js","6c6f855f7d50f4bc3c804f52b03bbfbb"],["/lib/pace/pace-theme-barber-shop.min.css","e8dc66cf2d88abc25fbc89b8a0529abb"],["/lib/pace/pace-theme-big-counter.min.css","db2b8fe31e60f19021545277d2f6e05e"],["/lib/pace/pace-theme-bounce.min.css","ad954aa0bace4b213eeb19d6e89a0bda"],["/lib/pace/pace-theme-center-atom.min.css","8f6bc803acefc6f93afc98fb38201456"],["/lib/pace/pace-theme-center-circle.min.css","93c72298781226a80a9c66b27b21a57d"],["/lib/pace/pace-theme-center-radar.min.css","f0099bdd1cd42e9476bd7abc417c0328"],["/lib/pace/pace-theme-center-simple.min.css","eddff4756dbf21dbbff1c543bd894dde"],["/lib/pace/pace-theme-corner-indicator.min.css","776826157cb28ac1ee5e78771292b9ba"],["/lib/pace/pace-theme-fill-left.min.css","965859b39001da08e1e92327fe3d8e12"],["/lib/pace/pace-theme-flash.min.css","aab39b436e1fa0fdc51df06f2d53c38a"],["/lib/pace/pace-theme-loading-bar.min.css","4e05877f1f9efb9c1e7dd75cb78c764f"],["/lib/pace/pace-theme-mac-osx.min.css","29ae030ceaa8158352c5472218375b91"],["/lib/pace/pace-theme-minimal.min.css","f48f04d370993b55a2745e548cc82743"],["/lib/pace/pace.min.js","24d2d5e3e331c4efa3cda1e1851b31a7"],["/lib/three/canvas_lines.min.js","1324174ae6190fbf63b7bf0ad0a8a5bd"],["/lib/three/canvas_sphere.min.js","5c6bc45b137448b5b9df152ccfb2659c"],["/lib/three/three-waves.min.js","41059bd5e5c7aa520b1b411919e5121f"],["/lib/three/three.min.js","3298078bce82bdb1afadf5b1a280915e"],["/lib/ua-parser-js/dist/ua-parser.min.js","a6e833266c4b41fabb9ba94a145322d8"],["/lib/ua-parser-js/dist/ua-parser.pack.js","6b627e4d61a7135952824bb9c1a4a134"],["/lib/velocity/velocity.js","0361fa6dcf4cf4d19c593cdab0937dd0"],["/lib/velocity/velocity.min.js","c1b8d079c7049879838d78e0b389965e"],["/lib/velocity/velocity.ui.js","f55d22cc592c9f8d4ffd3b41a6b90081"],["/lib/velocity/velocity.ui.min.js","444faf512fb24d50a5dec747cbbe39bd"],["/page/2/index.html","4bff6f60e0df6a019b37d935b421ab96"],["/page/3/index.html","3e2236043edf05aa767cba2a4342af40"],["/posts/13b6b7c2/index.html","3aaea4e8e771e56da5ff55ef21856c7d"],["/posts/143a0a72/index.html","bcdeb08a71b739de85977994e81bc717"],["/posts/1d6a9c79/index.html","0d501b55db2b72101dd6a070ea7c5a02"],["/posts/4370e84d/index.html","21f58896acd37ef4a572731ffa9a02eb"],["/posts/4a17b156/index.html","efda30400de5e39b9d6a8e3d94be2638"],["/posts/6021eb27/index.html","b99c8dc8885cae259205433059aee142"],["/posts/62e0a87a/index.html","1873da28dcb4f78a4f02122b89c810bb"],["/posts/6bfb34d8/index.html","b548a74fb60c4ea1cebb2f5ca658b47b"],["/posts/742c7f0a/index.html","b736f3f1392c9134ee651ce36f35539e"],["/posts/75c6e52f/index.html","5a2486f722adf8e2448f5aada591fe83"],["/posts/7a7093e6/index.html","eaef64c6cbd95cec212196c8dcd3bf5e"],["/posts/800507c2/index.html","e46c6b1f004c8410a9cc9824ed966f96"],["/posts/86ceb8f1/index.html","6ffad5b9f84108dea825c69395e57173"],["/posts/8786024c/index.html","f1f260b7fb42d1127ee0e47c360fedb7"],["/posts/8c3b0bac/index.html","345411dbcb4b44fa9631244be52973c3"],["/posts/948e1c93/index.html","f25d0d03824dbf423e71c9109d871de6"],["/posts/a5b005af/index.html","51b3e4d5bd507e7c6bea2b26f81781d0"],["/posts/a79c8cf7/index.html","6815b03676540f2846f48a39ab1f774a"],["/posts/bb07c3a7/index.html","a931dc3e1ba7db89f13c8749e291daca"],["/posts/bce46d0d/index.html","c6958df04cd958a2317e6b82cd4ea02a"],["/posts/c1c013be/index.html","d3333462a187f6692d1ce0ec5feb63da"],["/posts/cf0c10bf/index.html","f51e2b7fa0e485e3b72bd50cd2b0eb2f"],["/posts/d24e8921/index.html","0bc993545e67eb695bdc5eb84bcbcbbb"],["/posts/db1de468/index.html","0eb8ced8d69004e17173d7e7c42e1c4c"],["/posts/dd22b276/index.html","ea25735c0c5db39a23b3b0f5bf280393"],["/posts/e20ef482/index.html","d73f746e20c1b6f35bc6c53b0ecf13eb"],["/posts/e3c0f347/index.html","92b543e44eb6e64e8c966e0050cf9c29"],["/posts/e6939326/index.html","0abac9b326ab718205026afb4a188552"],["/posts/e913391a/index.html","d7b69169532523820388724c4ae43628"],["/posts/fd5cbc55/index.html","41ac6406f0f8a3121984bc063cdd5b1c"],["/sw-register.js","0684ed307a3119ee78b40eb18edb1d92"],["/tags/CSS/index.html","60beab7b8d1d595829b36b7b5ebd2bd0"],["/tags/ELK/index.html","d24051d99520e84e2b3c6ab460d1339c"],["/tags/FreeCodeCamp/index.html","6ed83d8ffa4b4757c7fb60fc44b11878"],["/tags/HTML/index.html","a26f3e5ea31f21b7ae49a3a104469770"],["/tags/HTML5/index.html","36b444444aa0803ddd0a0df767e8b433"],["/tags/Hadoop/index.html","c4336cb7727eb9930cd84e48fe21c9d7"],["/tags/Java/index.html","945bfea90ff547ce396560d44c6d504f"],["/tags/JavaScript/index.html","6aaeb2f2f01502cd4bfedc76e4186517"],["/tags/Linux/index.html","b2c2e3a5a9b0e5b1647480423ff0bf5d"],["/tags/Mac/index.html","0e6aad20b3896b73e00e4564eaaedf65"],["/tags/MapReduce/index.html","beefc69765c65b9fed924abcec65e997"],["/tags/MongoDB/index.html","19876ba8d034a81ca6abe3d53c38c3c3"],["/tags/MySQL/index.html","a0ec05763634e892b021c4471b392c7d"],["/tags/Windons/index.html","f24b21af4b2e84fdc54a4069fc35ac9e"],["/tags/blog/index.html","0afee5600e92e2c670ee076c750e57d6"],["/tags/index.html","4daa3163348a57f857a61db89ddba017"],["/tags/kali/index.html","3f481e50737a5cf976c2d438d566005a"],["/tags/seo/index.html","be340c3fa410f915248fa3d9ed13f11f"],["/tags/搜索技巧/index.html","4569fad62ffff50ad5a31c2cda70387b"],["/tags/方法论/index.html","a3405eef344b34b5b2d3cd9b8ef14c92"],["/tags/算法/index.html","23a3304df9a74d994b4faf2b729964af"],["/tags/计算机基础知识/index.html","43824011bad9308e0282fff6487f267c"],["/tags/面试/index.html","b3dcfe0118ae2ddcd6c6a448fb2007bc"],["/top/index.html","876c5876543cc3343bd7e872c83f0daa"]]; +var precacheConfig = [["/404.html","ce83d18b9d4c11bfb6386727d48e8900"],["/about/index.html","f280d0e9e48f5dd8816fde7f1043ffd0"],["/archives/index.html","78bb255b217209af299ce0246d31592c"],["/assets/css/APlayer.min.css","fbe994054426fadb2dff69d824c5c67a"],["/assets/css/DPlayer.min.css","31ac9b1a5a7f018dcc9a0e0f66261c08"],["/assets/js/APlayer.min.js","8f1017e7a73737e631ff95fa51e4e7d7"],["/assets/js/DPlayer.min.js","4097986cff510567068128f4b18004a6"],["/assets/js/Meting.min.js","bfac0368480fd344282ec018d28f173d"],["/baidu_verify_3NWlza1HUZ.html","83e87ab6389724fe2c5424542dbad50e"],["/categories/Java/index.html","da4d307c21b00861c8d8c95147a3f5d8"],["/categories/Linux/index.html","243d0042448a5ad32d09d6c8a8c0ba68"],["/categories/blog/index.html","980d0ccc0951e97eb02d8cfbfe0055e3"],["/categories/index.html","89362d5775af16fd641d3f5fe3e75073"],["/categories/web/index.html","b611a9e8d48efe689a44ba67ae5f7aab"],["/categories/web前端/index.html","3c37ae5efb7237f617f2ee1b56556da1"],["/categories/大数据/index.html","ea40742d523cd01e0d9a2ed94b261344"],["/categories/工具/index.html","12a18c77738a81802a512eb472616d91"],["/categories/数据库/index.html","e3a8070eef9e02d6bd64b92e393cbf86"],["/categories/方法论/index.html","154853246d0cdd3943e59ed7b16354cf"],["/categories/算法/index.html","e9b9f54027235930a6c44fc2fd62bd1a"],["/css/main.css","694b81f2955d9148a2067fdc5c4c10d5"],["/fonts/ComicNeue-Angular-Bold-Oblique.eot","40788a0a7b51a92389dad8b159492cb8"],["/fonts/ComicNeue-Angular-Bold-Oblique.ttf","7afa6bfc716544b765ad5d7bd61aa390"],["/fonts/ComicNeue-Angular-Bold-Oblique.woff","6c33764ad65ce89edd41147ec0f3541c"],["/fonts/ComicNeue-Angular-Bold-Oblique.woff2","31c870940de1afec23fc652600966664"],["/fonts/ComicNeue-Angular-Bold.eot","97bfd2726c48f293231900ed552e5fd9"],["/fonts/ComicNeue-Angular-Bold.ttf","3b3e96b257325929065b67d0b418b975"],["/fonts/ComicNeue-Angular-Bold.woff","fdfdec9d0b7dfa91fbe11dc2ec50473d"],["/fonts/ComicNeue-Angular-Bold.woff2","c58b01776b2adea50f334750eae72767"],["/fonts/ComicNeue-Angular-Light-Oblique.eot","d6047d25084572d7df4f0de2096b6703"],["/fonts/ComicNeue-Angular-Light-Oblique.ttf","4c9956b9278836ef07a7a806f45b264a"],["/fonts/ComicNeue-Angular-Light-Oblique.woff","4bf616657aa13c10ad173b7b738f2bab"],["/fonts/ComicNeue-Angular-Light-Oblique.woff2","3c074df0239e43a1f33f53483e4bc6bf"],["/fonts/ComicNeue-Angular-Light.eot","008b2822ea0c1c160df2b5ea2991a438"],["/fonts/ComicNeue-Angular-Light.ttf","43c1e8a3968b7fbdc2d98d1ca5dee684"],["/fonts/ComicNeue-Angular-Light.woff","34d7b4224ea5bbd30e4a3fbe8cc8a5e0"],["/fonts/ComicNeue-Angular-Light.woff2","f368a66f957ac4eb4e7f71fbfbbdb101"],["/fonts/ComicNeue-Angular-Regular-Oblique.eot","3e8299e59ae27259e71248832f99786c"],["/fonts/ComicNeue-Angular-Regular-Oblique.ttf","099285f76101ec3291f80cccdca21bdb"],["/fonts/ComicNeue-Angular-Regular-Oblique.woff","00f0e24953b6d6e71ca0891f974bfbdf"],["/fonts/ComicNeue-Angular-Regular-Oblique.woff2","808aab8b0462213b283ab1c0fea3c1d3"],["/fonts/ComicNeue-Angular-Regular.eot","3c6797b44cf639f15d940d5321a49a29"],["/fonts/ComicNeue-Angular-Regular.ttf","96e329b344475cfedef1867f8e002bee"],["/fonts/ComicNeue-Angular-Regular.woff","dec91b007193eb99bfb669e023356495"],["/fonts/ComicNeue-Angular-Regular.woff2","7b8d6bcdc8cb7acdb218aa5e314ac135"],["/fonts/ComicNeue-Bold-Oblique.eot","9623a2602e23e010df808efd573ded50"],["/fonts/ComicNeue-Bold-Oblique.ttf","6a2b4e115cc960db3e5fde8d95e82b6d"],["/fonts/ComicNeue-Bold-Oblique.woff","933e67b18c88f48694adcf02e9340a57"],["/fonts/ComicNeue-Bold-Oblique.woff2","65fd4add501504ffe42281c7c7f0b892"],["/fonts/ComicNeue-Bold.eot","a89b0d636179e835f1038cc1e7b11682"],["/fonts/ComicNeue-Bold.ttf","bb59dfb0d7fa8a0c9b7d431f94ff3d6d"],["/fonts/ComicNeue-Bold.woff","df4f1f0b09e7dcbf110e77a1a5ad936d"],["/fonts/ComicNeue-Bold.woff2","d8a5434f588f9e0f80e095907e6455d0"],["/fonts/ComicNeue-Light-Oblique.eot","3aed4284b4bf38f4ab7709f69a752ae2"],["/fonts/ComicNeue-Light-Oblique.ttf","805069ddfd6bdf57e01089ca90bb866f"],["/fonts/ComicNeue-Light-Oblique.woff","3b44b933104258988d9b125b71ac502f"],["/fonts/ComicNeue-Light-Oblique.woff2","5fcb8adbe863b29fb8f8695aae420e04"],["/fonts/ComicNeue-Light.eot","0e04ebae206c1fe27867e13405072635"],["/fonts/ComicNeue-Light.ttf","27219ea5f3a25dbf3a05903f34ed5bd6"],["/fonts/ComicNeue-Light.woff","780c9f200bbdd3ba13ac9464921ecabf"],["/fonts/ComicNeue-Light.woff2","1b00e4ccf3ff437d92a6958ca0660a73"],["/fonts/ComicNeue-Regular-Oblique.eot","07244e74afacb190403cc2028d56f2ab"],["/fonts/ComicNeue-Regular-Oblique.ttf","b0e3f8f6249f0bb895cd2f96fffee6cd"],["/fonts/ComicNeue-Regular-Oblique.woff","79cbff272c3231694b9d1dd44f8f38fc"],["/fonts/ComicNeue-Regular-Oblique.woff2","00110028a3c3c5fb1e3691d4de42a9ed"],["/fonts/ComicNeue-Regular.eot","3f916f08fa680d8e9ed4d8eaa4614629"],["/fonts/ComicNeue-Regular.ttf","c7823c53863f1386e0154142369242d6"],["/fonts/ComicNeue-Regular.woff","0689422546d69a1a7cffeff379ab42a0"],["/fonts/ComicNeue-Regular.woff2","884ec2a2c477fc7a6681218180011ac1"],["/fonts/font.css","b75a0621de61aaa3198b86ef16dae212"],["/guestbook/index.html","a0a3c41a3e06f2061208885a8bdde54a"],["/images/QRcode.svg","dbcc882694b4c7e7ea444fcc7b6fc7d4"],["/images/algolia_logo.svg","88450dd56ea1a00ba772424b30b7d34d"],["/images/apple-touch-icon-next.png","fce961f0bd3cd769bf9c605ae6749bc0"],["/images/avatar.gif","2bed513bc5f13733cf9a8a12c4e1a971"],["/images/cc-by-nc-nd.svg","3b009b0d5970d2c4b18e140933547916"],["/images/cc-by-nc-sa.svg","cf2644b7aa5ebd3f5eab55329b4e7cb7"],["/images/cc-by-nc.svg","e63bcae937a1ae4cb6f83d8a1d26893c"],["/images/cc-by-nd.svg","78359b1307baffc2d0e8cffba5dee2dd"],["/images/cc-by-sa.svg","525d2a82716fe9860a65cf0ac5e231a0"],["/images/cc-by.svg","bd656500a74c634b4ff1333008c62cd8"],["/images/cc-zero.svg","2d6242e90c3082e7892cf478be605d26"],["/images/es/es1.png","91fb15e343381b412947734c448c2de5"],["/images/es/es2.png","f985815b4f5c09399973e9e83986c8f6"],["/images/es/es3.png","f0db8ad81237e187bf8306db5bf33e40"],["/images/favicon-16x16-next.png","b8975923a585dbaa8519a6068e364947"],["/images/favicon-32x32-next.png","5a029563fe3214c96f68b46556670ea1"],["/images/h5-audio/1.webAudio-API.jpg","f1e9945bde46ee636eacd129857a5fa7"],["/images/h5-audio/2.AudioContext.jpg","cf62f9e59d6e97663a2c023ce2470f47"],["/images/h5-audio/3.GainNode.jpg","2f2ff1fade2dac6fafc17d9a2119b05c"],["/images/h5-audio/4.AudioBufferSourceNode.jpg","2ca1951f40c770452501e5383bfcffe8"],["/images/h5-audio/5.AnalyserNode.jpg","fdd6b7ba1e84d0b83576bc2216a1582b"],["/images/html-store/H51.jpg","9eb4ba5a95500c05af31d8e4213787f6"],["/images/html-store/H52.jpg","c9c9297860cb29f7669db0e0cf9ba516"],["/images/html-store/IndexedSQL.jpg","f6dd110a59bd9a9dc17cb782b5cf9bec"],["/images/icons/icon-128x128.png","e3b73bed589b8668cfb22689844cad91"],["/images/icons/icon-144x144.png","7d513e9d4c40c932e19003746fb449db"],["/images/icons/icon-152x152.png","041aaec9f001927a2ea2a9f02d266a8a"],["/images/icons/icon-72x72.png","901bddfccbbd720d9ada030274e90289"],["/images/icons/icon-96x96.png","1dce7fa7ee0ad689648b4e094697c317"],["/images/loading.gif","c2196de8ba412c60c22ab491af7b1409"],["/images/logo.svg","88985471c188e5c5a765a8f233c54df5"],["/images/mr-learn/HDFS.png","8dee230ff560ed8a446cdb201bb6776c"],["/images/mr-learn/MR1.png","bc0c135f5a655e2532c5de84d1c416ea"],["/images/mr-learn/MR10.png","5cb62d578f308a9e1cd74e9544714b42"],["/images/mr-learn/MR11.png","17a3469c9a7cf581bf108db879dbb98b"],["/images/mr-learn/MR12.png","40b01a18ab6a7cc7a9ace2a9f5934ced"],["/images/mr-learn/MR13.png","b1e59d1e062c9cb5102f96379cb219c7"],["/images/mr-learn/MR14.png","a9ceb9fe7be41e5d57400206871155da"],["/images/mr-learn/MR2.png","0dd9ae2e313b0b44e827ec2aa5b96522"],["/images/mr-learn/MR3.png","194aa203b5a98b43bea5b7c5935fe7ed"],["/images/mr-learn/MR4.png","cf17816d4bec8d2081cd66b339af4898"],["/images/mr-learn/MR5.png","a58cb9ee79cbad883e0585faa0996759"],["/images/mr-learn/MR6.png","2c642ab26af26511608f4ac6f1ad8691"],["/images/mr-learn/MR7.png","90336274950eaf68e8e709e31eb80a69"],["/images/mr-learn/MR8.png","9768f908cbae4cd0a2ed9a67984b5c3f"],["/images/mr-learn/MR9.png","a6de7726e7f92f7582f07a84b10432ae"],["/images/mr-learn/WordCount.png","0c0a5fc91489244c7beced3d8e135403"],["/images/mysql/base_sql.jpg","8b82bfa1d1f0a49d414fe1bf1c007aad"],["/images/mysql/mysql_char.jpg","9cb9cf51260af18a5bc696d11591c4b2"],["/images/mysql/mysql_data.jpg","646c53e376d5fb4a4d0511b0cfdf2f69"],["/images/mysql/mysql_float.jpg","7c3643254124a8ae456876c6de51e592"],["/images/mysql/mysql_int.jpg","f9088c1ebedee43f5c102c053accc726"],["/images/placeholder.gif","c2196de8ba412c60c22ab491af7b1409"],["/images/quote-l.svg","a9d75107c4d7e31612f98e78be0979f9"],["/images/quote-r.svg","5f902def9e09af7fc41e4cf86ad1a0f9"],["/images/searchicon.png","3d6b5c9d6d6c26a2b76a14b8fdf3438a"],["/images/temp/论文带读1/1585928401863.png","a6ab54bceeca40e973a54f3b58d6a144"],["/images/wechat.svg","2ef3f3696267249c4372a5e3f9db36f2"],["/images/wepay.svg","2e7265f61e62c0ce3af3e4b4713601ca"],["/index.html","a567e528e724349131a0b263e869cacd"],["/js/src/affix.js","683c19859764baf0d17538897ea1eba2"],["/js/src/algolia-search.js","f5fa392318805997089ceb3a925979ba"],["/js/src/bootstrap.js","2a1083772854ae2663748e0a25c17285"],["/js/src/exturl.js","2b444179b3145e5007b4d371dac07cd3"],["/js/src/hook-duoshuo.js","45997b0c06abff3cd88efd901f614065"],["/js/src/js.cookie.js","6e9eb1f53afb135aedaf90739c867738"],["/js/src/motion.js","0f6add86607c451269d0b3d286c84d8b"],["/js/src/post-details.js","b8e8e27c27c697567879c52888ffc24c"],["/js/src/schemes/pisces.js","827b5ad25e1142277c1e7dfe0cacebe5"],["/js/src/scroll-cookie.js","890406ae3539e4721ef5f314542e5e46"],["/js/src/scrollspy.js","fafdd7ab6af233b701506c733910b7f5"],["/js/src/utils.js","24512c3455f976730b7bf75e1222c533"],["/lib/Han/dist/font/han-space.woff","b09f2dd7d3ad8ad07f3b8495133909d9"],["/lib/Han/dist/font/han.woff","e841c6b547bc06a06f60f4de52bf906e"],["/lib/Han/dist/font/han.woff2","2b06aa1c952a2dfaf00d99218689d147"],["/lib/Han/dist/han.css","cfcc552e7aebaef5e2f34aee030b956b"],["/lib/Han/dist/han.js","575b6c1667c01798730fbd972e959c9c"],["/lib/Han/dist/han.min.css","cab466d758269b437167422c4a16b364"],["/lib/Han/dist/han.min.js","96482c9c2b3c5ea9bf5a40db162c7f34"],["/lib/algolia-instant-search/instantsearch.min.css","029a13b44e6807955106ff3c075a02f9"],["/lib/algolia-instant-search/instantsearch.min.js","0db46eba0c8133693ee839507b1612f2"],["/lib/canvas-nest/canvas-nest.min.js","36e103d2a05bc706bac40f9ab8881eb7"],["/lib/canvas-ribbon/canvas-ribbon.js","16dc214240913551986593808c2efcfc"],["/lib/fancybox/source/blank.gif","325472601571f31e1bf00674c368d335"],["/lib/fancybox/source/fancybox_loading.gif","328cc0f6c78211485058d460e80f4fa8"],["/lib/fancybox/source/fancybox_loading@2x.gif","f92938639fa894a0e8ded1c3368abe98"],["/lib/fancybox/source/fancybox_overlay.png","77aeaa52715b898b73c74d68c630330e"],["/lib/fancybox/source/fancybox_sprite.png","783d4031fe50c3d83c960911e1fbc705"],["/lib/fancybox/source/fancybox_sprite@2x.png","ed9970ce22242421e66ff150aa97fe5f"],["/lib/fancybox/source/helpers/fancybox_buttons.png","b448080f8615e664b7788c7003803b59"],["/lib/fancybox/source/helpers/jquery.fancybox-buttons.css","cac75538c2e3ddfadef839feaca8e356"],["/lib/fancybox/source/helpers/jquery.fancybox-buttons.js","f53c246661fb995a3f12e67fa38e0fa0"],["/lib/fancybox/source/helpers/jquery.fancybox-media.js","c017067f48d97ec4a077ccdf056e6a2e"],["/lib/fancybox/source/helpers/jquery.fancybox-thumbs.css","52ddd84a9f42c1d4cd86d518a7f7e8bc"],["/lib/fancybox/source/helpers/jquery.fancybox-thumbs.js","cf1fc1df534eede4cb460c5cbd71aba6"],["/lib/fancybox/source/jquery.fancybox.css","6c55951ce1e3115711f63f99b7501f3a"],["/lib/fancybox/source/jquery.fancybox.js","921e9cb04ad6e2559869ec845c5be39b"],["/lib/fancybox/source/jquery.fancybox.pack.js","cc9e759f24ba773aeef8a131889d3728"],["/lib/fastclick/README.html","b3cd6e7f930bf6e410a2e7eab8a148a8"],["/lib/fastclick/lib/fastclick.js","6e9d3b0da74f2a4a7042b494cdaa7c2e"],["/lib/fastclick/lib/fastclick.min.js","a0fc6c24d1f3ff9ac281887c92b24acd"],["/lib/font-awesome/css/font-awesome.css","c495654869785bc3df60216616814ad1"],["/lib/font-awesome/css/font-awesome.min.css","269550530cc127b6aa5a35925a7de6ce"],["/lib/font-awesome/fonts/fontawesome-webfont.eot","674f50d287a8c48dc19ba404d20fe713"],["/lib/font-awesome/fonts/fontawesome-webfont.svg","acf3dcb7ff752b5296ca23ba2c7c2606"],["/lib/font-awesome/fonts/fontawesome-webfont.ttf","b06871f281fee6b241d60582ae9369b9"],["/lib/font-awesome/fonts/fontawesome-webfont.woff","fee66e712a8a08eef5805a46892932ad"],["/lib/font-awesome/fonts/fontawesome-webfont.woff2","af7ae505a9eed503f8b8e6982036873e"],["/lib/jquery/index.js","32015dd42e9582a80a84736f5d9a44d7"],["/lib/jquery_lazyload/CONTRIBUTING.html","7287727950845c8a1010f3933691afef"],["/lib/jquery_lazyload/README.html","d89aa4afe316331a25b636b5ead4716e"],["/lib/jquery_lazyload/jquery.lazyload.js","8b427f9e86864ee3aaf1ae33e6e14263"],["/lib/jquery_lazyload/jquery.scrollstop.js","f163fd8f02361928853668a96f8a1249"],["/lib/needsharebutton/font-embedded.css","dd8861d10d1ed6b5e0c0011adfb39be9"],["/lib/needsharebutton/needsharebutton.css","30f2f800e13f7b6b83629a4cbd9749ef"],["/lib/needsharebutton/needsharebutton.js","6c6f855f7d50f4bc3c804f52b03bbfbb"],["/lib/pace/pace-theme-barber-shop.min.css","e8dc66cf2d88abc25fbc89b8a0529abb"],["/lib/pace/pace-theme-big-counter.min.css","db2b8fe31e60f19021545277d2f6e05e"],["/lib/pace/pace-theme-bounce.min.css","ad954aa0bace4b213eeb19d6e89a0bda"],["/lib/pace/pace-theme-center-atom.min.css","8f6bc803acefc6f93afc98fb38201456"],["/lib/pace/pace-theme-center-circle.min.css","93c72298781226a80a9c66b27b21a57d"],["/lib/pace/pace-theme-center-radar.min.css","f0099bdd1cd42e9476bd7abc417c0328"],["/lib/pace/pace-theme-center-simple.min.css","eddff4756dbf21dbbff1c543bd894dde"],["/lib/pace/pace-theme-corner-indicator.min.css","776826157cb28ac1ee5e78771292b9ba"],["/lib/pace/pace-theme-fill-left.min.css","965859b39001da08e1e92327fe3d8e12"],["/lib/pace/pace-theme-flash.min.css","aab39b436e1fa0fdc51df06f2d53c38a"],["/lib/pace/pace-theme-loading-bar.min.css","4e05877f1f9efb9c1e7dd75cb78c764f"],["/lib/pace/pace-theme-mac-osx.min.css","29ae030ceaa8158352c5472218375b91"],["/lib/pace/pace-theme-minimal.min.css","f48f04d370993b55a2745e548cc82743"],["/lib/pace/pace.min.js","24d2d5e3e331c4efa3cda1e1851b31a7"],["/lib/three/canvas_lines.min.js","1324174ae6190fbf63b7bf0ad0a8a5bd"],["/lib/three/canvas_sphere.min.js","5c6bc45b137448b5b9df152ccfb2659c"],["/lib/three/three-waves.min.js","41059bd5e5c7aa520b1b411919e5121f"],["/lib/three/three.min.js","3298078bce82bdb1afadf5b1a280915e"],["/lib/ua-parser-js/dist/ua-parser.min.js","a6e833266c4b41fabb9ba94a145322d8"],["/lib/ua-parser-js/dist/ua-parser.pack.js","6b627e4d61a7135952824bb9c1a4a134"],["/lib/velocity/velocity.js","0361fa6dcf4cf4d19c593cdab0937dd0"],["/lib/velocity/velocity.min.js","c1b8d079c7049879838d78e0b389965e"],["/lib/velocity/velocity.ui.js","f55d22cc592c9f8d4ffd3b41a6b90081"],["/lib/velocity/velocity.ui.min.js","444faf512fb24d50a5dec747cbbe39bd"],["/page/2/index.html","97ff1182a344106e76614351974fc50a"],["/page/3/index.html","b0bd43e569cbae7d4d89662c1c9f8f3d"],["/posts/13b6b7c2/index.html","48c3d315996ba9950da71fd7d560e116"],["/posts/143a0a72/index.html","dac4f524ccbb82dfc784dc6f1b2acbb2"],["/posts/1d6a9c79/index.html","b5e5c78fd79f5020e7c191e7a2281bc2"],["/posts/4370e84d/index.html","ce16caf77068076bd3f626ccf4ac7366"],["/posts/4a17b156/index.html","06c4d16df5b4a17f516bcd870fc7cf95"],["/posts/6021eb27/index.html","ba5257517eb984b32c0988ee71d624de"],["/posts/62e0a87a/index.html","762138a560e6f3737948fe1fa9937780"],["/posts/6bfb34d8/index.html","a836b937318d85b9cd07e75adbd2bb48"],["/posts/742c7f0a/index.html","9ca7c86d4a05ea8b668fd9d44ef4c6ca"],["/posts/75c6e52f/index.html","7c58310dff4929857b5a33d664ca0810"],["/posts/7a7093e6/index.html","1b1df61f8a6c678e993aa70ec3d48a71"],["/posts/86ceb8f1/index.html","d4e6f594972a7e4ced397a5514d23233"],["/posts/8786024c/index.html","a51a57635e4264a9210f759f37a0d7b1"],["/posts/8c3b0bac/index.html","0552ea77379a65ed410ed6f5bcf343a7"],["/posts/948e1c93/index.html","c5ea75c2c6ac6c198e2339c37a34c144"],["/posts/a5b005af/index.html","a3ba40d8fb3c53c2aaa01726e39abaaa"],["/posts/a79c8cf7/index.html","a168b251d1a592e03f4783220e5b9820"],["/posts/bb07c3a7/index.html","6cfad42eda81d952fddd869d854d5406"],["/posts/bce46d0d/index.html","d1c7ac65d6c1c1e9f69d7a177ccff4de"],["/posts/c1c013be/index.html","c000a650978b9359a58a658e887d6290"],["/posts/cf0c10bf/index.html","674f7016db5ef4a669adba50ef1a6a47"],["/posts/d24e8921/index.html","1fc4fad438bbf2d5e890b2fea02a8420"],["/posts/db1de468/index.html","0c28ed0caa2c0f95df1ddcb506577f02"],["/posts/dd22b276/index.html","d9673d791ff13b730379e21aff97c0e5"],["/posts/e20ef482/index.html","3e22d6e1f57b3d6efd76243049882096"],["/posts/e3c0f347/index.html","85253d786949b997f100d4c8319cea5b"],["/posts/e6939326/index.html","497b0fad262c8514943fc7080151876a"],["/posts/e913391a/index.html","913b8cfcee4017df268f826e9674a2de"],["/posts/fd5cbc55/index.html","56501ffca23ad7a1e3bc5a91a5397cda"],["/sw-register.js","bb6bfd5c6739b58deba65c502ccb5035"],["/tags/CSS/index.html","5f9e5ee08165b14f3026bc00b1e723bf"],["/tags/ELK/index.html","6cbee5bcc65d6ecec9c28c03ae2b8cdc"],["/tags/FreeCodeCamp/index.html","68c40c4bbb00125226c64b160881036b"],["/tags/HTML/index.html","c85fdb85e0bf76122f5ba19b7db7d0b0"],["/tags/HTML5/index.html","2d094fc89cc836fbfe13562ed2132754"],["/tags/Hadoop/index.html","f69577c2c1b801a656c94c0042d250c7"],["/tags/Java/index.html","986b456f7c2c53a0b37438c4d163681b"],["/tags/JavaScript/index.html","334b28982e26dff5d24267ff8ddd784f"],["/tags/Linux/index.html","8c50fbc1e2fde3b1e5d1d1dbf997b2e1"],["/tags/Mac/index.html","7a10d9a189dd589a464ea999dd9cc38d"],["/tags/MapReduce/index.html","7a283e54fc6759debc357c0e46b5bb46"],["/tags/MongoDB/index.html","5ed323e40eea32b1be8d7a99209f411b"],["/tags/MySQL/index.html","8473b2e44db582398599b8decb2fa6bf"],["/tags/Windons/index.html","60223677bbcb98fa2488d9467fdc59f1"],["/tags/blog/index.html","09006ab23c008a505c77607d519fd2b0"],["/tags/index.html","6807ac5720d7828e6e4a5337d3874fde"],["/tags/kali/index.html","82ecb17bb49e265967a47cb6e0c55ba7"],["/tags/seo/index.html","6cee3e05a80a0f1de89584189eda6bc7"],["/tags/搜索技巧/index.html","a5e4e34cdd0a8a7171899a3fc3a5c65b"],["/tags/方法论/index.html","d7ab7ef0181797d38e49308fa2381917"],["/tags/算法/index.html","679a2ee62a905c0294784b2c53d9c571"],["/tags/计算机基础知识/index.html","c35f969355d37f794f0fc109b9e1b7f2"],["/tags/面试/index.html","fddb9f2a2e2d30ad61fec86ee9215215"],["/top/index.html","eb35efdee9aae84dbaae9b9b97e40430"]]; var cacheName = 'sw-precache-v3--' + (self.registration ? self.registration.scope : ''); var firstRegister = 1; // 默认1是首次安装SW, 0是SW更新 diff --git a/tags/ELK/index.html b/tags/ELK/index.html index 4f86abdc..93640f78 100644 --- a/tags/ELK/index.html +++ b/tags/ELK/index.html @@ -461,7 +461,7 @@

- 30 + 29 日志 @@ -1305,7 +1305,7 @@