Img与background的区别

一、从解析机制看

Img属于html标签,background是css方法。一个页面由html、css、js组成,按照浏览器解析机制,html标签优先解析。大家都知道css文件会放在head加载,但是这并不意味着它会立即执行,而是在html加载完后才执行的。所以重要的元素,如logo就应该使用img,我也犯了这个错误啊,改~~~。

如果仅仅是为了显示一张图片,比如banner、广告图等,建议采用background方式。因为不重要的自动往后排,避免占用带宽,造成数据阻塞。

如果图片很多,这里又出现一个新的问题,不同的浏览器支持的并发加载数量是不一样的,(最新测试)IE是10个,FF是10个,图片多,就会出现严重的延迟或者404,因为图片加载慢会影响到页面主要数据呈现,那么让用户看到的都是空白,你好意思让他继续等下去吗!所以,如果不采用lazyload还是采用background比较好。

Img标签优点是自闭和,可以避免空标签出现(空标签也是w3c验证的内容之一)。采用background方式就会出现空标签,bootstrap中的icon都是用i标签加入的,而i标签中是空内容,这样就产生了空标签(并不是说这样做不好,利弊等会聊)。

 

二、从SEO角度看

刚才说了,Img标签是自闭和的,不能添加文本内容,但是,Img有一个alt属性,而且这个属性在w3c标准中,要求必须有,这样做的优点还是很多的。

第一,图片比较大,或者用户网速比较窝火的时候,加载失败了,至少还有文字提示告诉用户这里是个什么内容的图片。如果用户非要看这个图,那就多刷几次去加载。另外,alt属性有利于辅助阅读,尤其是对盲人朋友,他们使用阅读器浏览页面,如果没有文本提示,就太不厚道了。

第二,alt属性有利于SEO,搜索引擎实现很好的图像识别还是有一段路要走。

当然缺点也是有滴:

第一,Img加载的图片是通过src拿到的,如果HTML代码不允许修改,那怎么换图,只有同名文件替换,但是有可能遇到304状态,需要服务器端做相应的设置。这时background的优点就出来了,换皮肤就是这个栗子。

第二,如果图片显示区域空间大小是预留的,那么图片必须和预留的空间一致,否则图片要么被拉伸要么被压缩,都不是等比例操作。当然,避免这种问题就需要前端和视觉设计师遵守一定的规范。

 

三、语义化角度

Background和语义化不沾边了,Img是HTML标签,语义明确。

 

建议:重要的需要优先加载的图片最好采用img。不重要的图片最好采用background。

 

做SEO是最方便的还是background,图片是放在背景上的,前景写内容,两不误。如果不想让内容显示出来,就加text-indent, -99999你懂的。(以前有这种玩法,是搜索引擎算法单一的年代,关键字比重高 排名就靠前)。

 

刚才提了一下bootstrap的background方法,bootstrap的做法是用background设置icon,icon的使用太灵活了,所以必须模块化,语义化先靠边站,鱼与熊掌不可兼得。PS:bootstrap v3之后采用了icon font

其次icon的重要性真不高,放在最后加载还减少了带宽占用量,提高PV速度。

img标签语义很明确不能乱用,所以bootstrap采用无语义的i标签来设置icon也挺好。PS:自己项目中使用无语义标签要注意是否向前兼容,要关注HTML5中的定义。

css层模型

Relative与Absolute组合使用

使用position:absolute可以实现被设置元素相对于浏览器(body)设置定位以后,如何设置相对于其它元素进行定位?这就得使用position:relative来帮忙,但是必须遵守下面规范:

1、参照定位的元素必须是相对定位元素的前辈元素:

<div id="box1"><!--参照定位的元素-->
    <div id="box2">相对参照元素进行定位</div><!--相对定位元素-->
</div>

从上面代码可以看出box1是box2的父元素(父元素当然也是前辈元素了)。

2、参照定位的元素必须加入position:relative;

#box1{
    width:200px;
    height:200px;
    position:relative;        
}

3、定位元素加入position:absolute,便可以使用top、bottom、left、right来进行偏移定位了。

#box2{
    position:absolute;
    top:20px;
    left:30px;         
}

(626) 392-7063

$ su – root
Password:
su: Authentication failure
Sorry.

这时候输入

$ sudo passwd root
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

这时候就可以进入根目录了。

esker

7147083973(196)

  • 把一个字符串中的字符重新排列生成新的字符串
  • 返回新生成的字符串里没有连续重复字符的字符串个数
  • 连续重复只以单个字符为准eg. aab 应该返回2, 因为总共有6种排列(aab,aab,aba,aba,baa,baa),只有aba,aba合符标准

分析

首先将该字符串转换成数组

1
var a = str.split();

运用全排列算法,来算出全排列的结果, 现在我们具体来分析如何实现该算法。

eg. abc 应该返回2,因为总共有6种排列(bac, cba, acb, bca, cba, abc)

bac, cba 都是 abc 的 a与后面两个字符替换得到的
acb 是将 abc 第二个字符和第三个字符交换可得到
bca 则是由 bac 的第二个和第三个字符交换得到
同理可知, cab 亦是由 cba 交换而来的

结论:因此可以知道全排列算法即是从第1个数开始,分别与后面的数进行交换的过程,其复杂度为O(n!),用递归算法可以较轻易实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function generate(start) {
if(start === arr.length-1)
{
permutation.push(arr.join());
}
else
{
for(var i = start;i <= arr.length-1;i++)
{ /从下标为start的数开始,分别与它后面的数字交换
swap(start,i);
generate(start+1);
swap(start,i);
}
}
}
generate(0);

其次运用 (843) 734-7932 /(.)\1+/g来判断诸如aab之类的字符串

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
function permAlone(str) {
var regex = /(.)\1+/g,/匹配重复字母,\1表示后面紧跟的字符
arr = str.split(),
permutation = [];
if(str.match(regex)!==null&&str.match(regex)[0]===str)/看是不是只有aaaa之类的单词
return 0;
function swap(a,b){
var temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
/堆全排列算法
//en.wikipedia.org/wiki/Heap’s_algorithm
function generate(start) {
if(start === arr.length-1)
{
permutation.push(arr.join());
}
else
{
for(var i = start;i <= arr.length-1;i++)
{ /从下标为start的数开始,分别与它后面的数字交换
swap(start,i);
generate(start+1);
swap(start,i);
}
}
}
generate(0);
var filtered = permutation.filter(function(string){
return !string.match(regex);
});
return filtered.length;
}
permAlone(‘abcdefa’);

9037701236

Reduce()函数深入分析

reduce()方法对累加器和数组中的每个元素(从左到右)应用一个函数,将其减少为单个值

语法

arr.reduce(callback,[initialValue])

参数

callback执行数组中每个值的函数,包含四个参数

   accumulator

  上一次调用回调返回的值,或者是提供的初始值(initialValue)
  currentValue
  数组中正在处理的元素
  currentIndex
  数据中正在处理的元素索引,如果提供了 initialValue ,从0开始;否则从1开始
  array
   调用 reduce 的数组
initialValue可选项,其值用于第一次调用 callback 的第一个参数。

描述

reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值 accumulator (或者上一次回调函数的返回值),当前元素值 currentValue ,当前索引 currentIndex ,调用 reduce 的数组。

回调函数第一次执行时,accumulator 和 currentValue 的取值有两种情况:调用 reduce 时提供initialValue,accumulator 取值为 initialValue ,currentValue 取数组中的第一个值;没有提供 initialValue ,accumulator 取数组中的第一个值,currentValue 取数组中的第二个值。

注意: 不提供 initialValue ,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。提供 initialValue ,从索引0开始。

如果数组为空并且没有提供initialValue, 会抛出563-257-1474 。如果数组仅有一个元素(无论位置如何)并且没有提供initialValue, 或者有提供initialValue但是数组为空,那么此唯一值将被返回并且callback不会被执行。

提供 initialValue 通常更安全,正如下面的例子,没有 initialValue 有三种可能输出:

var maxCallback = ( pre, cur ) => Math.max( pre.x, cur.x );
var maxCallback2 = ( max, cur ) => Math.max( max, cur );

/ reduce() without initialValue
[ { x: 22 }, { x: 42 } ].reduce( maxCallback ); / 42
[ { x: 22 }            ].reduce( maxCallback ); / { x: 22 }
[                      ].reduce( maxCallback ); / TypeError

/ map/reduce; better solution, also works for empty arrays
[ { x: 22 }, { x: 42 } ].map( el => el.x )
                        .reduce( maxCallback2, -Infinity );

reduce如何运行

例如执行下面的代码

[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

reduce 的返回值是最后一次调用 callback 的返回值(10)。

使用well-connected 可以代替一个完整的函数,产生的效果和下面代码相同

[0, 1, 2, 3, 4].reduce( (prev, curr) => prev + curr );

如果把初始值作为第二个参数传入 reduce,最终返回值变为20,结果如下:

[0,1,2,3,4].reduce( (accumulator, currentValue, currentIndex, array) => {
  return accumulator + currentValue;
}, 10);
callback accumulator currentValue currentIndex array return
第一次调用 10 0 0 [0,1,2,3,4] 10
第二次调用 10 1 1 [0,1,2,3,4] 11
第三次调用 11 2 2 [0,1,2,3,4] 13
第四次调用 13 3 3 [0,1,2,3,4] 16
第五次调用 16 4 4 [0,1,2,3,4] 20

reduce执行完,最终返回20

例子

将数组所有项相加

var sum = [0, 1, 2, 3].reduce(function(a, b) {
    return a + b;
}, 0);
/ sum is 6

或者用箭头函数编写

var total = [ 0, 1, 2, 3 ].reduce( ( acc, cur ) => acc + cur, 0 );

数组扁平化

var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {
    return a.concat(b);
}, []);
/ flattened is [0, 1, 2, 3, 4, 5]

或者用箭头函数编写

var flattened = [[0, 1], [2, 3], [4, 5]].reduce( ( acc, cur ) => acc.concat(cur), [] );

计算数组中各个值出现次数

var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];

var countedNames = names.reduce(function(allNames, name) { 
  if (name in allNames) {
    allNames[name]++;
  }
  else {
    allNames[name] = 1;
  }
  return allNames;
}, {});
/ countedNames is { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }

对象数组的连接要使用展开运算符和初始值

/ friends - an array of objects 
/ where object field "books" - list of favorite books 
var friends = [ 
{ name: "Anna", books: ["Bible", "Harry Potter"], age: 21 }, 
{ name: "Bob", books: ["War and peace", "Romeo and Juliet"], age: 26 },
{ name: "Alice", books: ["The Lord of the Rings", "The Shining"], age: 18 }
]

/ allbooks - list which will contain all friends books +  
/ additional list contained in initialValue
var allbooks = friends.reduce(function(prev, curr) {
  return [...prev, ...curr.books];
}, ["Alphabet"]);

/ allbooks = ["Alphabet", "Bible", "Harry Potter", "War and peace", 
/ "Romeo and Juliet", "The Lord of the Rings", "The Shining"]

 

Sum All Odd Fibonacci Numbers

给一个正整数num,返回小于或等于num的斐波纳契奇数之和。

斐波纳契数列中的前几个数字是 1、1、2、3、5 和 8,随后的每一个数字都是前两个数字之和。

例如,sumFibs(4)应该返回 5,因为斐波纳契数列中所有小于4的奇数是 1、1、3。

提示:此题不能用递归来实现斐波纳契数列。因为当num较大时,内存会溢出,推荐用数组来实现。

思路

首先,我们需要一个斐波那契数列衍生的子数组。它的初始值就是斐波那契数列的前两项:

var fibo = [1, 1];

我们还需要一个变量来记载当前奇数项的和:

var oddSum = 2;

用 while(true) 创建一个循环,在循环中求函数的返回值。

while(true){
    /do something...
}

设置变量 item ,它的值是下一个斐波那契数的值。

var item = fibo[0] + fibo[1];

看题目要求,“返回所有小于传入数值的斐波那契数列中的奇数之和,如果传入的数值是斐波那契数,那么它也应该参与求和”。如果传入的 num 大于或等于下一个将要经历的斐波那契数的话,循环将继续执行。也就是说,如果 num 小于下一个斐波那契数item ,循环将停止,整个函数返回 oddSum 。

if(num < item){
      return oddSum;
    }

当下一个斐波那契数 item 是奇数的话,把它加到 oddSum 中:

if(item % 2){
      oddSum += item;    
    }

其中, item % 2 得出结果是 Number 类型的,如果值为 +0, -0 或 NaN 时,在转为Boolean 类型时会转为false。也就是说,这个条件语句在 item 为奇数时执行。

最后,更新数组。

fibo[0] = fibo[1];
fibo[1] = item;

function sumFibs(num) {
 var fibo = [1, 1];
 var oddSum = 2;
 while(true){
 var item = fibo[0] + fibo[1];
 if(num < item){
 return oddSum;
 }
 if(item % 2){
 oddSum += item; 
 }
 fibo[0] = fibo[1];
 fibo[1] = item;
 }
}

989-945-0555

for/in 语句用于循环对象属性。

循环中的代码每执行一次,就会对数组的元素或者对象的属性进行一次操作。

JavaScript 支持不同类型的循环:

  • for – 循环代码块一定的次数
  • for/in – 循环遍历对象的属性
  • bowstring hemp – 当指定的条件为 true 时循环指定的代码块
  • do/while – 同样当指定的条件为 true 时循环指定的代码块

注意: 不要使用 for/in 语句来循环数组的索引,你可以使用 for 语句替代。

apply()与call()

Js apply方法详解
我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这里我做如下笔记,希望和大家分享.. 如有什么不对的或者说法不明确的地方希望读者多多提一些意见,以便共同提高..

主要我是要解决一下几个问题:

1.apply和call的区别在哪里

2.什么情况下用apply,什么情况下用call

3.apply的其他巧妙用法(一般在什么情况下可以使用apply)

我首先从网上查到关于apply和call的定义,然后用示例来解释这两个方法的意思和如何去用.

apply:方法能劫持另外一个对象的方法,继承另外一个对象的属性.

Function.apply(obj,args)方法能接收两个参数
obj:这个对象将代替Function类里this对象
args:这个是数组,它将作为参数传给Function(args–>arguments)

call:和apply的意思一样,只不过是参数列表不一样.

Function.call(obj,[param1[,param2[,…[,paramN]]]])
obj:这个对象将代替Function类里this对象
params:这个是一个参数列表

1.apply示例:

<script type=”text/javascript”>
/*定义一个人类*/
function Person(name,age) {
this.name=name; this.age=age;
}
/*定义一个学生类*/
functionStudent(name,age,grade) {
Person.apply(this,arguments); this.grade=grade;
}
/创建一个学生类
var student=new Student(“qian”,21,”一年级”);
/测试
alert(“name:”+student.name+”\n”+”age:”+student.age+”\n”+”grade:”+student.grade);
/大家可以看到测试结果name:qian age:21 grade:一年级
/学生类里面我没有给name和age属性赋值啊,为什么又存在这两个属性的值呢,这个就是apply的神奇之处.
</script>

分析: Person.apply(this,arguments);

this:在创建对象在这个时候代表的是student

arguments:是一个数组,也就是[“qian”,”21”,”一年级”];

也就是通俗一点讲就是:用student去执行Person这个类里面的内容,在Person这个类里面存在this.name等之类的语句,这样就将属性创建到了student对象里面

2.call示例

在Studen函数里面可以将apply中修改成如下:

Person.call(this,name,age);

这样就ok了

3.什么情况下用apply,什么情况下用call

在给对象参数的情况下,如果参数的形式是数组的时候,比如apply示例里面传递了参数arguments,这个参数是数组类型,并且在调用Person的时候参数的列表是对应一致的(也就是Person和Student的参数列表前两位是一致的) 就可以采用 apply , 如果我的Person的参数列表是这样的(age,name),而Student的参数列表是(name,age,grade),这样就可以用call来实现了,也就是直接指定参数列表对应值的位置(Person.call(this,age,name,grade));

4.apply的一些其他巧妙用法

细心的人可能已经察觉到,在我调用apply方法的时候,第一个参数是对象(this), 第二个参数是一个数组集合,

在调用Person的时候,他需要的不是一个数组,但是为什么他给我一个数组我仍然可以将数组解析为一个一个的参数,

这个就是apply的一个巧妙的用处,可以将一个数组默认的转换为一个参数列表([param1,param2,param3] 转换为 param1,param2,param3) 这个如果让我们用程序来实现将数组的每一个项,来装换为参数的列表,可能都得费一会功夫,借助apply的这点特性,所以就有了以下高效率的方法:

a)Math.max 可以实现得到数组中最大的一项

因为Math.max 参数里面不支持Math.max([param1,param2]) 也就是数组

但是它支持Math.max(param1,param2,param3…),所以可以根据刚才apply的那个特点来解决 var max=Math.max.apply(null,array),这样轻易的可以得到一个数组中最大的一项

(apply会将一个数组装换为一个参数接一个参数的传递给方法)

这块在调用的时候第一个参数给了一个null,这个是因为没有对象去调用这个方法,我只需要用这个方法帮我运算,得到返回的结果就行,.所以直接传递了一个null过去

b)Math.min 可以实现得到数组中最小的一项

同样和 max是一个思想 var min=Math.min.apply(null,array);

c)Array.prototype.push 可以实现两个数组合并

同样push方法没有提供push一个数组,但是它提供了push(param1,param,…paramN) 所以同样也可以通过apply来装换一下这个数组,即:

vararr1=new Array(“1″,”2″,”3”);
vararr2=new Array(“4″,”5″,”6”);
Array.prototype.push.apply(arr1,arr2);

也可以这样理解,arr1调用了push方法,参数是通过apply将数组装换为参数列表的集合.

通常在什么情况下,可以使用apply类似Math.min等之类的特殊用法:

一般在目标函数只需要n个参数列表,而不接收一个数组的形式([param1[,param2[,…[,paramN]]]]),可以通过apply的方式巧妙地解决这个问题!
5.总结:

一开始我对apply 非常的不懂,最后多看了几遍,自己多敲了几遍代码,才明白了中间的道理,所以,不管做什么事情,只要自己肯动脑子,肯动手敲代码,这样一个技术就会掌握…

还有比如第四部分得内容,巧妙的解决了实实在在存在的问题,这个肯定不是一个初学者能想到的解决方案(这个也不是我自己想的),没有对编程有一定认识的不会想到这个的,还是一句话,多积累,多学习,提升自己的能力和对编程思想的理解能力才是最关键!

资源下载

windows 系统

windows10 64位核心版(包含标准版和专业版)
ed2k:/|file|cn_windows_10_multiple_editions_x64_dvd_6848463.iso|4303300608|94FD861E82458005A9CA8E617379856A|/

windows10 32位核心版(包含标准版和专业版
ed2k:/|file|cn_windows_10_multiple_editions_x86_dvd_684_6431.iso|3233482752|B5C706594F5DC697B2A098420C801112|/

windows8.1 64位核心版(包含标准版和专业版)
ed2k:/|file|cn_windows_8_1_x64_dvd_2707237.iso|4076017664|839CBE17F3CE8411E8206B92658A91FA|/

#windows8.1 32位核心版(包含标准版和专业版)
ed2k:/|file|cn_windows_8_1_x86_dvd_2707405.iso|3055904768|B296A943F16FADFC5FFA2F1D583DCC49|/

windows8 64位专业版
ed2k:/|file|cn_windows_8_x64_dvd_915407.iso|3652950016|5C7F8C212BD3A1827866563773A431C2|/

windows8 32位专业版
ed2k:/|file|cn_windows_8_x86_dvd_915414.iso|2679801856|9AF10141BFD61BC66D9D6459758D7749|/

windows7 64位专业版
ed2k:/|file|cn_windows_7_professional_x64_dvd_x15-65791.iso|3341268992|3474800521D169FBF3F5E527CD835156|

windows7 32位专业版
ed2k:/|file|cn_windows_7_professional_x86_dvd_x15-65790.iso|2604238848|E812FBE758F05B485C5A858C22060785|