JiM-W

keep Moving


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

Angular Js directive

发表于 2016-10-21 | 分类于 javascript

1 自定义指令中的scope属性详解

几种缓存的总结

发表于 2016-10-19 | 分类于 javascript

几种缓存的总结

1 DNS缓存

  • 为了增加访问效率,计算机有域名缓存机制,当访问过某个网站并得到其IP后,会将其域名和IP缓存下来,下一次访问的时候,就不需要再请求域名服务器获取IP,直接使用缓存中的IP,提高了响应的速度。当然缓存是有有效时间的,当过了有效时间后,再次请求网站,还是需要先请求域名解析。
  • 但是域名缓存机制也可能会带来麻烦。例如IP已变化了,仍然使用缓存中的IP来访问,将会访问失败。再如 同一个域名在内网和外网访问时所对应的IP是不同的,如在外网访问时通过外网IP映射到内网的IP。同一台电脑在外网环境下访问了此域名,再换到内网来访问此域名,在DNS缓存的作用下,也会去访问外网的IP,导致访问失败。根据情况,可以手动清除DNS缓存或者禁止DNS缓存机制。

2 CDN缓存

  • 用户在浏览网站的时候,浏览器能够在本地保存网站中的图片或者其他文件的副本,这样用户再次访问该网站的时候,浏览器就不用再下载全部的文件,减少了下载量意味着提高了页面加载的速度。
  • 如果中间加上一层CDN,客户端浏览器先检查是否有本地缓存是否过期,如果过期,则向CDN边缘节点发起请求,CDN边缘节点会检测用户请求数据的缓存是否过期,如果没有过期,则直接响应用户请求,此时一个完成http请求结束;如果数据已经过期,那么CDN还需要向源站发出回源请求(back to the source request),来拉取最新的数据

3 浏览器端缓存

http缓存 localStorage缓存 sessionStorage缓存 cookies缓存 application cache缓存

4 服务器缓存

如何解决移动端两栏自适应的问题

发表于 2016-10-18 | 分类于 mobile

如何解决移动端两栏自适应的问题?overflow:hidden

要求:第一水平方向不要有滚动条;第二,水平第一个侧栏宽度固定,第二个侧栏宽度自适应

1 明确元素的宽度:块级元素 默认占据整行,如果不设置宽度,则默认和父元素等宽;行内块元素的宽度由内容决定,可以自行设置;行内元素的宽度由内容决定,不可设置宽高;

2 设置了浮动或者定位的层的宽宽由内容决定,发生元素转换,display:inline-block;

3 目的是实现 :右边栏的宽度 = 屏幕宽度 - 左边栏宽度 ,以此来实现右边栏里面的内容进行百分比设置宽度以自适应屏幕的时候,是以 右边栏的宽度 = 屏幕宽度 - 左边栏宽度 为基准的。

4 注意理解块级元素的流体特性:在默认情况下(非浮动、定位),块级元素会默认在水平方向自动填满外部的容器(自动填满父元素)。

5 浮动元素left和触发了BFC特性的元素right,right栏自适应,right设置overflow:hdden,触发BFC特性,即可实现right自动填充剩余的空间,而不是那种文字环绕图片的效果。

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
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
<!--设置移动端视觉窗口,宽度和移动终端设备等宽-->
<style>
body{
margin: 0;
padding: 0;
}
.phone {
width: 100%;
height: 100%;
position: absolute;
border: 1px solid #000000;
}
.left{
width: 90px;
height: 100%;
float: left;
background: red;
overflow: hidden;
}
/*产出一个绝缘的盒子 别的浮动不影响它 它也不影响其他的浮动,
左边盒子设置浮动,宽度固定*/
/*bfc*/
.right{
height: 100%;
background-color: skyblue;
overflow: hidden;
}
/*可以点击绿色按钮,看下右边层的宽度,两种情况overflow:hidden 存在与否,overflow:hidden触发了BFC使其不会受浮动元素的影响,同时其也不会影响浮动元素
overflow存在的时候,可使右边的盒子自动填充剩余的宽度,以实现自适应布局*/
input {
display:block;
height: 40px;
width: 30px;
background-color: green;
}
img{
width: 50%;
/*根据right的宽度为基准进行设置自身的宽度,以此来实现自适应布局*/
}
</style>
</head>
<body>
<div class="phone">
<div class="left"></div>
<div class="right">
<input type="button"/>
<img src="img/01.jpg" alt="" />
</div>
</div>
<script>
document.querySelector("input").onclick=function(){
console.log("bingo");
var right = document.querySelector(".right")
console.log(right.offsetWidth);
};
</script>
</body>
</html>

6 注意:高潮来了,如何设置left和right之间的间隙呢?

  • 给right设置margin-right 或者 padding-left
1
2
3
4
.right {
margin-left:100px;
}
结果是left和right还是粘连在一起,不起作用,因为BFC元素设置margin-left和float元素混排是不起作用的
1
2
3
4
.right {
padding-left:20px;
}
这个会起作用,可以将两栏隔开一定的距离
  • 给left设置margin-right 或者 padding-right 来撑开两栏之间的间隙
1
2
3
4
5
.left {
padding-right:20px ;
或者
margin-right:20px ;
}

7 BFC自适应布局的组件化代码

1
2
3
4
5
6
7
.left{
float:left;
margin-right:20px;
}
.right {
overflow:hidden ;
}

8 如果是右边栏宽度固定,左边栏宽度自适应呢?

解析顺序不同会导致占位不同,所以只需要将右边写在左边前面即可

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
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
<!--设置移动端视觉窗口,宽度和移动终端设备等宽-->
<style>
body{
margin: 0;
padding: 0;
}
.phone {
/*width: 320px;*/
/*height: 480px;*/
width: 100%;
height: 100%;
position: absolute;
border: 1px solid #000000;
}
.left{
height: 100%;
background-color: skyblue;
overflow: hidden;
/*两栏自适应留白*/
}
/*产出一个绝缘的盒子 别的浮动不影响它 它也不影响其他的浮动*/
/*bfc*/
.right{
width: 90px;
height: 100%;
float: right ;
background: red;
}
/*右边盒子设置自适应的宽度*/
input {
display:block;
height: 40px;
width: 30px;
background-color: green;
z-index: 999;
}
img{
width: 50%;
}
</style>
</head>
<body>
<div class="phone">
<div class="right">
<input type="button"/>
</div>
<div class="left"></div>
</div>
<script>
document.querySelector("input").onclick=function(){
console.log("bingo");
var right = document.querySelector(".right")
console.log("右边盒子宽度:"+right.offsetWidth);
};
</script>
</body>
</html>

Angular Js angularModule

发表于 2016-10-17 | 分类于 javascript

1 模块的定义

module是angular中重要的模块组织方式,它提供了将一组内聚的业务组件(controller、service、filter、directive…)封装在一起的能力。这样做可以将代码按照业务领域问题分module的封装,然后利用module的依赖注入其关联的模块内容,使得我们能够更好的”分离关注点“,达到更好的”高内聚低耦合“。”高内聚低耦合“是来自面向对象设计原则。内聚是指模块或者对象内部的完整性,一组紧密联系的逻辑应该被封装在同一模块、对象等代码单元中,而不是分散在各处;耦合则指模块、对象等代码单元之间的依赖程度,如果一个模块的修改,会影响到另一个模块,则说明这两模块之间是相互依赖紧耦合的。

同时module也是我们angular代码的入口,首先需要声明module,然后才能定义angular中的其他组件元素,如controller、service、filter、directive、config代码块、run代码块等。

关于module的定义为:angular.module(‘com.ngbook.demo’, [])。关于module函数可以传递3个参数,它们分别为:

  1. name:模块定义的名称,它应该是一个唯一的必选参数,它会在后边被其他模块注入或者是在ngAPP指令中声明应用程序主模块;
  2. requires:字符串的参数列表;模块的依赖,它是声明本模块需要依赖的其他模块的参数。特别注意:如果在这里没有声明模块的依赖,则我们是无法在模块中使用依赖模块的任何组件的;它是个可选参数。
  3. configFn: 模块的启动配置函数,在angular config阶段会调用该函数,对模块中的组件进行实例化对象实例之前的特定配置,如我们常见的对$routeProvider配置应用程序的路由信息。它等同于”module.config“函数,建议用”module.config“函数替换它。这也是个可选参数。

我们可以打印出来angular全局对象和angular.module()这个方法返回的对象来更深入的了解它们之间的关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>mudule submit</title>
<script src="./bower_components/angular/angular.js"></script>
</head>
<body >
<script>
console.dir(angular);
console.dir(angular.module("myModule",[]));
</script>
</body>
</html>

2 声明module之后,其他组件元素,如controller、service、filter、directive、config代码块、run代码块也就可以在对应的模块上使用了。

Object对象assign方法

发表于 2016-10-13 | 分类于 javascript

JS中深拷贝和浅拷贝

一 : 先来区分下一个小的细节 点操作符 和 [ ] 操作 对象属性的时候的区别

1
2
3
4
5
6
var arr = [12,13,14];
for(key in arr){
console.log(key); //输出数组的索引 0,1,2···
console.log(arr.key); //undefined undefined undefined
console.log(arr[key]); // 12 13 14
}
1
2
3
4
5
6
7
8
9
10
var obj = {
name:"Jhon",
age:13,
address:"American"
}
for(key in obj){
console.log(key); // name age address
console.log(obj.key); //undefined undefined undefined
console.log(obj[key]); // Jhon 13 American
}
1
2
3
4
5
6
7
8
9
10
11
12
var obj = {
name:"Jhon",
age:13,
address:"American"
}
console.log(obj.name) //Jhon
console.log(obj["name"]) //Jhon
var key = "name";
console.log(obj[key]) //Jhon
console.log(obj.key) //Jhon
//[] 可以接受变量,点操作符不可以

二 下面来实现一个浅拷贝的源码: 浅拷贝是指在复制一个对象的时候,仅仅对第一层的键值对进行复制,第二层的对象复制的是一个地址

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
function shadowCopy (target,source){
if(!source || typeof source !== 'object'){ //source必须是对象
return;
}
if(!target || typeof target !== 'object'){
return;
}
for(var key in source){
if(source.hasOwnProperty(key)){
target[key] = source[key];//注意必须用[]形式,不能用点操作符
}
}
}
var obj1 = {
name:"Jhon",
age:13,
address:"American",
other:{ //other是一个对象
gender:"man"
}
}
var obj2 = {};
shadowCopy(obj2,obj1);
console.dir(obj2);
//浅拷贝有一个问题,就是复制的obj2中的other和obj1中的other指向的是同一个对象
obj1.name = "JiM";
obj1.other.gender = "woman"; //修改obj1中的属性gender
console.log(obj2.name);//Jhon // obj2中的name不会跟着改变
console.log(obj2.other.gender);//woman //obj2中的gender也跟着改变
//基本数据类型复制传值,复杂数据类型的复制传地址,这个是内因
//这是浅拷贝的一个缺陷,虽然说也拷贝了一份,但是对于对象的拷贝不够彻底

三 深拷贝原理如下:用到了递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function deepCopy (target,source){
if(!source || typeof source !== 'object'){ //source必须是对象
return;
}
if(!target || typeof target !== 'object'){
return;
}
for(var key in source){
if(source.hasOwnProperty(key)){
if(source[key] && typeof source[key] == 'object'){
target[key] = {};
deepCopy(source[key],target[key]);
}else{
target[key] = source[key];
}
}
}
}

注意数组的slice和concat方法其实是一种浅复制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
var arr = [{
id : 1,
price : '40',
},{
id : 2,
price : '30',
},{
id : 3,
price : '60',
},{
id : 4,
price : '30',
}];
var newArr = arr.slice(0); //复制数组
console.dir(newArr);
console.dir(newArr[0].id); //1
arr[0].id = 666;
console.dir(newArr[0].id); //666
</script>

Object assign

发表于 2016-10-13 | 分类于 javascript

1 先来看下字符串,数字和布尔类型转化为对象包装类

1
2
3
4
5
6
console.log(Object('abc'));
console.log(typeof Object('abc'));
console.log(Object(1));
console.log(typeof Object(1));
console.log(Object(true));
console.log(typeof Object(true));

2 Object.assign(target,source1,source2,······);该方法会将source1,2对象的 可枚举的属性复制到target对象上,然后返回target对象

2.1 如果只传了一个参数,那么直接返回该参数,(如果传的是基本数据类型null和undefined会报错),基本数据类型转化为包装对象,复杂数据类型直接返回

1
2
3
4
5
Object.assign(undefined) // 报错
Object.assign(null) // 报错
typeof Object.assign(2) // "object"
var obj = {a: 1};
Object.assign(obj) === obj // true

2.2 如果传递了多个参数,那么进行赋值拷贝,注意assign方法执行的是浅拷贝,也就是说如果键值的值是复杂数据类型,那么复制的是地址,如果source有包装类型字符串可以进行赋值,null undefined 数字以及布尔类型会跳过

1
2
3
4
5
var obj1 = {a: {b: 1}};
var obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
obj2.a.b // 2

2.3 如果对象target的属性和source的属性名有重复的,那么会进行合并覆盖

1
2
3
4
var target = { a: { b: 'c', d: 'e' } }
var source = { a: { b: 'hello' } }
Object.assign(target, source)
// { a: { b: 'hello' } }

2.4 原型上的属性以及不可枚举的属性不会被复制

1
2
3
4
5
6
7
8
9
10
11
12
var obj = Object.create({ foo: 1 }, { // foo is on obj's prototype chain.
bar: {
value: 2 // bar is a non-enumerable property.默认emunerable属性值是false
},
baz: {
value: 3,
enumerable: true // baz is an own enumerable property.
}
});
var copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }

3 assign经常的用法,以下代码都是有联系的

1
2
3
let x = 'jhon';
let y = 'jim'
console.log(Object.assign({},{x,y}));//ES6对象的属性简写,如果x y未定义会报错

3.1 为对象添加属性

1
2
3
4
5
6
//第一用法添加对象的属性
class test {
constructor(){
Object.assign(this,{x,y});//这里是对象的简写
}
}

3.2 为对象添加方法

1
2
3
4
5
6
7
8
9
10
11
12
//第二个用法,添加对象的方法
Object.assign(test.prototype,{
method1(){
console.log("this is method one");
},
method2(){
console.log("this is method two");
}
})
var t = new test();
console.log(t);

3.3 克隆对象

1
2
3
4
5
6
7
8
9
10
11
12
function clone(origin){
return Object.assign({},origin);
};
//如果想要克隆原型上的属性
function perfectClone(origin){
let originPrototype = Object.getPrototypeOf(origin);
return Object.assign(originPrototype,origin);
}
var c = clone(t);
console.log(c);
var pc = perfectClone(t);
console.log(pc);

3.4 合并多个对象

1
2
3
const merge = (target,source1,source2) => Object.assign(target,source1,source2);
var M = merge(t,c,pc);
console.log(M);

3.5 为属性指定默认值

1
2
const DEFAULTS = {name:"Jhon",psw:"123456"};
let loginIn = (option) => {option = Object.assign({},DEFAULTS,option)};

Arrayfrom API ES6

发表于 2016-10-13 | 分类于 javascript ES6

Array.from(arrayLike[, mapFn[, thisArg]]) 该方法从一个类似数组或可迭代对象创建一个新的数组实例

  • 第一个参数是一个类数组对象,
  • 第二个参数作为map函数的callback执行,
  • 第三个参数是执行mapFn时候的this指向
  • 返回值是一个新的数组实例

关于类数组对象只要该对象中有length属性, 即可认为是类数组对象

1 将类数组转化为数组

先抛出一个问题,这个也是在网上看到的

如何不使用loop循环,创建一个长度为100的数组,并且每个元素的值等于它的下标?

以下测试均在chorm浏览器,火狐有的版本会直接初始化为undefined

1
2
3
//很多人第一步如下
var arr = Array(100);//但是这个是稀疏数组
console.log(arr) ;//[]

如果使用Array.from就很简单了

1
2
3
Array.from(arr);//这就成功创建了一个密集数组,所有的值都被初始化未undefined
Array.from({length:100});//这个和上面达成的效果是一致的
//[undefined,undefined,undefined···········]

然后通过Object.keys(obj) 该方法返回obj对象的所有可枚举的属性的键值组成的 数组;

1
2
Object.keys(Array.from({length:100}))
//[1,2,3,4······100]

当然了上面这些是ES6的新特性,如何在ES5中达到类似的效果呢?方法其实也很多

方法1 :

1
2
3
4
var arrayLike = {length:100};
var arr1 = [];
arr1.push.apply(arr1,arrayLike );
console.log(arr1);////[undefined,undefined,undefined···········]

方法2 :

1
2
3
4
var arrayLike = {length:100};
var arr2 = Array.apply(null,arrayLike ); //Array方法也是为了创建一个新的数组
//注意必须用apply,apply会将传入的数组或者类数组对象中的属性一一传入调用apply的函数中
console.log(arr2);////[undefined,undefined,undefined···········]

然后同样调用Object.keys(obj)方法即可;

2 将类数组转化的数组实例通过mapFn函数加工,返回一个加工后的数组

1
2
3
var arrayLike = {0:11,1:12,2:13,length:3};
var newArr = Array.from(arrayLike,item => item*2);
console.log(newArr);//[22,24,26]

Array API ES6

发表于 2016-10-02 | 分类于 ES6

ES5 数组新增API

1 数组的length属性,该属性是可读可写的

1
2
3
4
var arr = ['Jhon',66,"JiM"];
console.log(arr.length);//3
arr.length = 4 ;
console.log(arr[4]);//undefined

2 Array.isArray(value) 该方法用来判断传递进来的参数是不是数组,如果是则返回true,否则返回false;

Array.from(arrayLike[, mapFn[, thisArg]])

参数

  • arrayLike

    想要转换成真实数组的类数组对象 (只要该对象有length属性即可)或可遍历对象

  • mapFn

    可选参数,如果指定了该参数,则最后生成的数组会经过该函数的加工处理后再返回。

  • thisArg

    可选参数,执行 mapFn 函数时 this 的值。

返回值

一个新的Array实例

1
2
3
Array.from("foo"); // // ["f", "o", "o"]
// 使用 map 函数转换数组元素
Array.from([1, 2, 3], x => x + x); // [2, 4, 6]

3 Array.prototype.map (callback,thisArg ) 数组的map方法将向callback函数中传递三个参数,依次是每个数组元素,当前数组元素的索引,当前数组,callback执行的返回值 会作为数组元素添加到一个新的数组中去;

1
Array.prototype.map(callback,thisArg);//thisArg严格模式下指向undefined ,非严格模式指向window
1
2
3
4
5
var numberArr = [36,25,9,16];
var newNum = numberArr.map(Math.sqrt);
console.log(newNum);//[6,5,3,4]
console.log(numberArr);// [36,25,9,16]
//map方法返回一个新的数组,不改变原数组
1
2
3
4
5
6
7
8
9
//如何利用map方法获取每一个字符串的编码值
var str = "Learn more for great life";
var map = Array.prototype.map;
var strArr = map.call(str,function(s){
// 'use strict'
console.log(this) ;//注意函数内部的this指向是window,'use strict'严格模式下是undefined;
return s.charCodeAt(0);//注意必须有返回值,如果没有return ,默认返回undefined,生成的是一个undefined组成的数组
});
console.log(strArr);
1
2
3
4
5
6
7
8
//如何利用map方法翻转一个字符串,现将字符串转化为数组,然后将数组翻转,在将数组转化为字符串
var str = "Learn more for great life";
var map = Array.prototype.map;
var strArr = map.call(str,function(s){
return s;
});
var newStr = strArr.reverse().join("");
console.log(newStr);

在网上又看到了一个更好地办法

1
2
var str = '1234567';
var revStr = str.split("").reverse().join('');
1
2
3
4
5
6
7
8
9
//猜一猜这个返回的数组是什么?
var arr = [1,2,3,4];
var newArr = arr.map(parseInt);
console.log(newArr);
//parseInt函数其实接受的是两个参数 parseInt(s,radix)一个是要转化的字符串,一个是转化的进制基数;
//map函数传递给callback的是三个参数,一个数组元素,一个数组元素的索引值,一个是数组本身;
//其实执行的是以下过程
//parseInt(1,0) parse(2,1) parseInt(3,2) parseInt(4,3) 对于parseInt如果基数为0 ,按照十进制进行转化
//所以输出结果是 [1 ,NaN,NaN,NaN]

3.1 callback 函数只会在有值的索引上被调用;那些数组中未初始化的元素或者使用 delete删除的索引则不会被调用

1
2
3
4
5
6
var arr1 = new Array(100);
console.log(arr1);
var arr = arr1.map(function(item,index){
return index; //未被初始化的数组元素并不会调用callback函数
})
console.log(arr);//空数组

4 Array.prototype.forEach( callback , thisArg ) 数组的forEach 方法向callback回调函数中传递3 个参数,依次是每个数组元素,当前数组元素的索引,当前数组,forEach API 不像map API ,forEach每次执行callback并没有接受返回值,也不会返回一个数组,而map会将callback的返回值(如果没有显式的返回,则默认undefined),形成一个新的数组,然后返回这个新的数组;

1
Array.prorotype.forEach(callback,thisArg) //thisArg严格模式下指向undefined ,非严格模式指向window
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//thisArg可以用来改变forEach的callback函数执行时候this指向
function Counter(){
this.sum = 0;
this.count = 0 ;
}
Counter.prototype.add = function(array){
array.forEach(function(item){
this.sum += item ;
++this.count;
console.log(this);//看下这个时候的this指向
},this);
}
var arr = [9,6,2];
var counter = new Counter();
counter.add(arr);
console.log(counter.sum);
console.log(counter.count);

4.1 forEach 没有办法中止或者跳出 forEach 循环,除了抛出一个异常

1
2
3
4
var arr = [1,2,3,4]
arr.forEach(function(item){
console.log(item);//1,2,3,4
})
1
2
3
4
5
var arr = [1,2,3,4]
arr.forEach(function(item){
console.log(item);
break;//抛出异常
})

4.2 如果在遍历的过程中,某个元素被删除了,那么会直接跳过该元素

1
2
3
4
5
6
7
8
9
10
11
var arr = [0,1,2,3,4,5,6,7]
arr.forEach(function(item,index,arr){
console.log("item"+item);
console.log("index"+index);
console.log(arr);
//index 会从索引0一直递增,如果期间删除了某一项,会使后面的元素所在索引位置发生变化
if(item === 2){
arr.shift();
console.log(arr);
}
})

4.3 forEach函数的返回值是undefined,所以它不能像map或者reduce函数那样,可以链式调用数组的方法,因为map函数会将callback每次的返回值存在一个数组中整体返回

1
2
3
4
5
6
var str = "Learn more for great life";
var foreach = Array.prototype.forEach;
var res = foreach.call(str,function(s){
return s;
});
console.log(res);//undefined

4.4 forEach 方法按升序为数组中含有效值的每一项执行一次callback 函数,那些已删除(使用delete方法等情况)或者未初始化的项将被跳过(但不包括那些值为 undefined 的项)

1
2
3
4
5
var arr1 = new Array(100);//创建一个未被初始化的数组,数组的长度为100
console.log(arr1);
arr1.forEach(function(item){
console.log(item);//并不会输出任何值
})

5 Array.prototype.every( callback , thisArg ) 数组的every方法向callback回调函数中传递3 个参数,依次是每个数组元素,当前数组元素的索引,当前数组,返回值是布尔类型;当执行某个元素返回值是false的时候,终止every函数的执行,返回false;只有当每个元素执行结果为true,最终才能返回true;

而 Array.prototype.some(callback ,thisArg) 和every基本上一样,只要有一个数组元素执行callback结果是true,那么就返回true,停止当前循环,不再进行后面的循环遍历操作;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Parameters
callback
Function to test for each element, taking three arguments:
currentValue (required)
The current element being processed in the array.
index (optional)
The index of the current element being processed in the array.
array (optional)
The array every was called upon.
thisArg
Optional. Value to use as this when executing callback.
Return value
true if the callback function returns a truthy value for every array element; otherwise, false.
Description
The every method executes the provided callback function once for each element present in the array until it finds one where callback returns a falsy value. If such an element is found, the every method immediately returns false. Otherwise, if callback returns a truthy value for all elements, every returns true. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
1
2
3
4
5
6
function isBigEnough(element, index, array) {
return element >= 10;
}
[12, 5, 8, 130, 44].every(isBigEnough); // false
[12, 54, 18, 130, 44].every(isBigEnough); // true

6 Array.prototype.reduce(callback ,[initialValue]) (reduceRight函数和reduce函数类似,只不是从数组的最后反向开始迭代);数组的reduce方法向callback函数传递四个参数,分别是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Parameters
callback
Function to execute on each value in the array, taking four arguments:
1 accumulator
The accumulated value previously returned in the last invocation of the callback, or initialValue, if supplied. (See below.)(如果initialValue提供了,那么第一次运行的时候,accumular值为initialValue,如果没有提供initialValue,那么accumular的值为数组中的第一个元素,currentValue为数组中的第二个元素,跳过第一个索引值)
2 currentValue
The current element being processed in the array.
3 currentIndex
The index of the current element being processed in the array. Starts at index 0, if an initialValue is provided, and at index 1 otherwise.
4 array
The array reduce was called upon.
5 initialValue
Optional. Value to use as the first argument to the first call of the callback.
Return value
The value that results from the reduction.

reduce如何工作?

1
2
3
4
5
6
7
8
9
10
[0, 1, 2, 3, 4].reduce(
  function (
accumulator,
  currentValue,
  currentIndex,
  array
) {
return accumulator + currentValue;
}
);
callback accumulator currentValue currentIndex array return value
first call 0 1 1 [0, 1, 2, 3, 4] 1
second call 1 2 2 [0, 1, 2, 3, 4] 3
third call 3 3 3 [0, 1, 2, 3, 4] 6
fourth call 6 4 4 [0, 1, 2, 3, 4] 10
1
2
3
4
5
6
[0, 1, 2, 3, 4].reduce(
  (accumulator, currentValue, currentIndex, array) => {
return accumulator + currentValue;
},
10
);
callback accumulator currentValue currentIndex array return value
first call 10 0 0 [0, 1, 2, 3, 4] 10
second call 10 1 1 [0, 1, 2, 3, 4] 11
third call 11 2 2 [0, 1, 2, 3, 4] 13
fourth call 13 3 3 [0, 1, 2, 3, 4] 16
fifth call 16 4 4 [0, 1, 2, 3, 4] 20

reduce将callback函数的返回值作为accumulator传递给callback重复执行;

ruduce函数经常用来扁平化数组

1
2
3
4
5
6
7
var Flatten = [[1,2],[4,6],[7,9]]
var newFaltten = Flatten.reduce(function(a,b){
return a.concat(b);
},[])
console.log(Flatten);
console.log(newFaltten);

7 Array.prototype.filter( callback ,thisArg ) filter向callback传递参数 依次是每个数组元素,当前数组元素的索引,当前数组。该方法返回一个新的数组,不改变原数组; filter函数对每个数组元素进行判断,满足条件的会保存下来,返回到新的数组当中,不满足条件的话进行下一个数组元素的判断(其实本质是如果callback函数返回true,那么保留当前数组元素,如果callback函数返回false,不保留该数组元素,那么进行对下一个数组元素的判断)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var arr = [2,3,4,5,6,7,8];
var newArr = arr.filter(function(item){
return item > 4 ;
});
console.log(arr); //[2,3,4,5,6,7,8];
console.log(newArr);//[5,6,7,8]
//-----------------------------------------------
var arr = [2,3,4,5,6,7,8];
var newArr = arr.filter(function(item){
return true ;
});
console.log(arr); //[2,3,4,5,6,7,8]
console.log(newArr); //[2,3,4,5,6,7,8]
//如果是return false ;那么newArr = [] ;如果没有返回值,callback默认返回undefined,filter对undefined转化为false ,最后newArr还是空数组;
//如果return 数字 字符串 等等 返回结果都是原来的数组,因为filter会对callback函数的返回值进行转化为布尔类型的值进行判断,如果转化结果为true ,那么则保留当前数组元素,如果转化结果为false,则不保留当前数组元素

8 Array.prototype.keys( ) 返回的结果是一个Array迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var arr = ['ma','jje','fff']
let iterator = arr.keys()
console.log(iterator)
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
/**
Array Iterator {}
Object {value: 0, done: false}
Object {value: 1, done: false}
Object {value: 2, done: false}
Object {value: undefined, done: true}
*/
let Arr = ['a',,'c']
let sparseKeys = Object.keys(Arr)
let denseKeys = [...Arr.keys()]
console.log(sparseKeys) //["0","2"]
console.log(denseKeys) //[0,1,2]
//需要注意的一点就是Object.keys() 返回的是一个由字符串索引组成的数组

9 Array.prototype.indexOf()

indexOf 使用strict equality (无论是 ===, 还是 triple-equals操作符都基于同样的方法)进行判断 searchElement与数组中包含的元素之间的关系。

注意比较下面的情况,对于复杂数据类型,比较的是引用地址是否指向同一个地址,如果是则能找到,返回其对应的索引值,如果不是,则找不到,返回-1

1
2
3
var arr = [{text:"JHon"},{text:"Jim"}]
var ret = arr.indexOf({text:"JHon"})
console.log(ret) //-1
1
2
3
4
var obj = {text:"JHon"}
var arr = [obj,{text:"Jim"}]
var ret = arr.indexOf(obj)
console.log(ret) //0

Array Sort

发表于 2016-10-02 | 分类于 javascript

数组的sort方法—-改变原数组

简单粗暴直接上代码咯(sort方法的定义请查阅W3C或者搜索)

注意:sort(fn) 方法可以接受一个 方法为参数 ,这个方法有两个参数。分别代表每次排序比较时的两个数组项。sort()排序时每次比较两个数组项都回执行这个参数,并把两个比较的数组项作为参数传递 给这个函数。

当函数返回值为 1 的时候就交换两个数组项的顺序,否则就不交换。 

sort方法排序的关键是在于传入函数的返回值;改变原数组,并不产生新的数组;如果fn这个参数被省略,那么元素将按照 ASCII 字符顺序进行升序排列。

一 数字类型数组排序

1
2
3
4
5
6
7
8
9
var arr = [21,35,24,12,15,2,3,65,64]
arr.sort(function(){
console.log(arguments);
console.log(this);
})
//从控制台结果可以看出sort传递的函数默认有两个参数,这两个参数就是要排序的数组里面的两项
//函数执行的this指向window;
//如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,是按照字符编码的顺序进行排序。
1
2
3
4
5
6
7
8
var arr = [21,35,24,12,15,2,3,65,64]
arr.sort(function(a,b){
return a - b ;
})
//这种方法可以排序数字数组,却不能排序字符串数组,如下有代码案例
console.log(arr);
//注意 - 操作符的运算,对于数字类型的运算数,结果返回数字
//a-b输出从小到大排序,b-a输出从大到小排序。
1
2
3
4
5
var arr = ['eca','bda','acf','dfe'];
arr.sort()
console.log(arr);
//["acf", "bda", "dfe", "eca"]
//如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较
1
2
3
4
5
6
7
8
var arr = ['eca','bda','acf','dfe'];
arr.sort(function(a,b){
return a - b ;
})
//这种方法不能排序字符串
console.log(arr);
//["eca", "bda", "acf", "dfe"]
//这个排序功能就没有了,因为 - 运算符操作的运算数如果有一个不是数字,那么就会返回NaN,没有返回1 -1 或者0任意一个;

二 字符串数组排序

那么如何才能排序字符串呢?这个之前需要先了解,字符串的比较 < <= > >= 返回一个布尔类型的值

对于字符串,第一个字符串中每个字符的代码都与会第二个字符串中对应位置的字符的代码进行数值比较。完成这种比较操作后,返回一个 Boolean 值。

所以对于字符串的排序,需要进行比较运算的运用,判断字符代码的大小,然后选择返回 1 -1 还是 0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var arr = ['eca','bda','acf','dfe'];
function sortStr (str1,str2){
if(str1 > str2){ //如果str1 > str2 交换二者的位置
return 1 ;
}else if (str1 < str2 ){ //如果str1 < str2 则不交换
return -1;
}else{
return 0;
}
}
arr.sort(sortStr);
console.log(arr);
//["acf", "bda", "dfe", "eca"] 按字母升序排列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var arr = ['eca','bda','acf','dfe'];
function sortStr (str1,str2){
if(str1 > str2){
return -1 ;//1 变为-1
}else if (str1 < str2 ){
return 1;// -1 变为1
}else{
return 0;
}
}
arr.sort(sortStr);
console.log(arr);
//["eca", "dfe", "bda", "acf"] 按字母降序排列

此方法通用数字数组

三 如果数组里面存放一组对象呢?如何按照对象的某一个数据进行排序?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function sortByProperty(sortName){
return function (o1,o2){
if(o1[sortName] > o2[sortName] ){
return 1 ;
}else if(o1[sortName] < o2[sortName]){
return -1 ;
}else{
return 0 ;
}
}
}
arr.sort(sortByProperty("id"))
console.log(arr);
//同样,可以按照不同的属性进行排序

四 如何打乱一个随机数组

1
2
3
4
5
6
7
function randomsort(a, b) {
return Math.random()>.5 ? -1 : 1;
//用Math.random()函数生成0~1之间的随机数与0.5比较,返回-1或1
}
var arr = [1, 2, 3, 4, 5];
arr.sort(randomsort);
console.log(arr);

或者更简洁

1
2
3
arr.sort(function(){
return Math.random() - 0.5;
})

Git command detail Reset

发表于 2016-09-30 | 分类于 git

1 撤销修改

git checkout – index.html

一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;

一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

总之,就是让这个文件回到最近一次 git commit 或 git add 时的状态。

git reset HEAD index.html

git reset 命令既可以回退版本,也可以把暂存区的修改回退到工作区;也就是说将添加到暂存区的修改退回到工作区;当我们用HEAD时,表示最新的版本。

再用git status查看一下,现在暂存区是干净的,工作区有修改:

1…91011…20
JiM-W

JiM-W

keep fighting!

195 日志
52 分类
90 标签
© 2017 JiM-W
由 Hexo 强力驱动
主题 - NexT.Pisces