昨晚5点多睡觉,早上12点才起床,下午爬去参加了珠海的 GDG。主讲是 360 的一个高级网络工程师(我才知道珠海也有 360 的分部),还有一个腾讯的员工,讲的内容一般般,收获还是有一点的。晚上又折腾了一下 deepin 操作系统,打算还是暂时不碰 Linux。睡前先把首页的原型图大概切一下先。
首页原型图
明天再做详细的切图啦,今天实在太累了……GG思密达
今天顿生无聊,感觉陷入一个瓶颈,所以打算开一个新的项目——
Oxygen轻音乐
,比较简单的一个收藏自己喜欢的歌的网站,结合自己之前学过的东西进行整理,从中发现不足,进行下一步学习。同时也可以得到一些Nope.js
的新函数的灵感,不废话,先进行一下需求分析和技术分析。
参照一下 UI 设计图,并作修改
播放器背景使用高斯模糊对相应歌曲图片处理
今天在微博看到有人发了一道题目,代码如下:
|
|
getName()
,这里调用的是第 7 行的函数,有人要问了,为什么不是第 8 行,这里涉及到JS解析器中一个function declaration hoisting(函数声明提升)
的过程,在 JS 代码中,使用var x = function(){}
叫作函数表达式
,使用function x(){}
叫作函数声明
,在 JS 代码加载的过程中,函数声明会在第一时间加载到源代码树的顶部,所以即使你调用使用函数声明的函数比该函数的声明还早,也是无异常的。反之,函数表达式则要在 JS 加载到该行代码时,函数才算是真正可以使用。所以这道题里,第 8 行比第 7 行的函数声明早,所以第7行的函数表达式覆盖了第 8 行的函数内容。
Foo().getName()
,这里执行 Foo() 后返回的 this 是 window,即全局对象,而 Foo() 内部的getName
由于没有使用 var 去声明,故默认为 window 的 getName 属性,所以又再一次覆盖了原先的 getName(),所以打印是1。
getName()
,由于上一行代码的执行已经导致了 window 下的 getName() 被覆盖,所以依旧打印1。
new Foo.getName()
,这里 new 的是 getName() 而不是 Foo(),所以打印了2,与第 10 行的调用方法类似,不过这里还会返回一个 Foo.getName 的实例。
new Foo().getName()
,这里首先 new Foo() 返回 Foo() 的实例对象,这里注意,构造函数中如果没有指明 return,那么默认返回构造函数的实例,如果指定了 return,那么返回指定的 return 的值(只能是引用类型的值,如{},[]等),这里指定了 return this,this 在 new 的情况下是实例本身,所以跟默认情况下是一致的,然后又调用了 getName(),这里调用的是原型中的函数,所以打印3。
new new Foo().getName()
,先不看第一个 new,则后面的步骤跟上面一致,不过到了调用函数的时候,第一个 new 发生作用了,实例化了 getName(),不过这里的 getName() 依旧是原型中的函数,只不过将他实例化了,所以依旧打印3。
|
|
.clearfix:after {content:"."; display:block; height:0; visibility:hidden; clear:both; }
这里也是一种方法,content
为一个.
的原因是在 Firefox 里,空的 content 会有额外间隙,所以使用.
,此外的height
等属性只是为了隐藏 content 不影响布局。而最新的方法 display: table
的 content 可以为空,且不会产生间隙,所以额外的属性都可以去除。
在父元素使用overflow
清除浮动的原理是,将父元素变为一个新的BFC
,根据 BFC 的特点,BFC 可以包含浮动元素,所以,不仅仅是 overflow 能清除浮动,只要能触发父元素的BFC的方式都可以清除浮动,例如display: table-cell
,float:left
等等都可以触发BFC。
传统的加一个空的div去清除浮动的方法有一个缺点,当子元素是浮动元素且有外边距是,清除浮动以后,父元素的高度仅仅是包裹子元素的高度(不包括外边距的高度),那么子元素明显会被边距顶出了父元素外边,虽然父元素会被撑开一段高度,但是由于子元素外边距的存在,父元素无法完全包裹子元素。
关于BFC的知识,可浏览
IE,Chrome都有window.event
对象
FireFox没有window.event
对象
|
|
以上写法能保证在这三个浏览器下获取事件对象和当前事件元素的兼容性。
首先,使用 typeof
去判断一个函数是一种通用的做法,不过这种做法存在一种风险,即在低版本浏览器下会出现误判的现象,在 IE6/7/8 下,一些 JS 的核心函数是以 COM
对象去构造的函数,例如 document.getElementById
,正常情况下,typeof 应该对其判断为 function
,但是在 IE6/7/8 下,会将其判断为 object
。
在 Chrome 和 Safari 的旧版本中,正则表达式
进行 typeof 的判断结果为 function
,其他浏览器则返回 object
,这会导致误判,所以使用 typeof 判断函数是一种不稳定的做法,存在一定的风险。
[object Object]
,这是 IE 特有的 JScript
所导致的,IE 中一些函数是以 COM
对象构造的。正则表达式
的返回就正确了,结果为 [object RegExp]
。总结:在 IE9+ 和比较新的 Chrome、Safari 下,用 typeof 还是很方便的,而且效率比使用第二种方法快得多,在100万次的执行效率对比下,typeof 判断完消耗时间大概为4.5ms
,而 Object.prototype.toString 则消耗高达50ms
以上,其效率差距10几倍。以下代码可以判断是否使用 typeof 判断 Function:
|
|
|
|
|
|
使用该种方法,浮动在右边的div必须写在左边div之前
|
|
|
|
diplay: table 在IE上仅支持IE 8及以上版本
|
|
|
|
flex 布局仅支持 IE 10+、Chrome 21+、Firefox 22+、Safari 6.1+、Opera 12.1+
CORS 的实现相对简单,当我们使用 XMLHttpRequest 进行跨域时,会给request的地址加入一个 Origin 头部,其中包含请求页面的源信息(
eg. Origin: http://www.baidu.com
),如果服务器接收到 request 后,需要给 response 加上 Access-Control-Allow-Origin 头部(eg. Access-Control-Allow-Origin: http://www.baidu.com
),当然,如果是公共资源,将地址改成*
就可以允许所有源地址进行跨域访问。如果服务器没有加入和 Origin 头部地址对应的头部或者 Access-Control-Allow-Origin 允许的跨域地址不相符合(eg. Access-Control-Allow-Origin: http://www.google.com
),那么浏览器将会驳回请求,导致跨域失败。
XDomainRequest(以下简称XDR)是IE部分实现CORS规范的一个类型,和 XMLHttpRequest(以下简称XHR)不同的是,XDR 有以下不同:
使用 XMLHttpRequest(以下简称XHR)跨域和 XDR 跨域不同之处有以下几点:
同时,跨域 XHR 也有以下限制(每个浏览器安全策略不同,例如chrome可以对跨域的XHR使用setRequestHeader):
Preflighted Requests 是一种透明服务器验证机制,使用即可支持开发人员使用自定义头部、GET 或 POST 以外的方法以及不同类型的主体内容。上面提到跨域XHR不能使用 setRequestHeader() 设置自定义头部,如果使用了 setRequestHeader() 设置自定义头部(eg. xhr.setRequestHeader(“halo”, “loha”)),那么在发出正式请求之前,浏览器首先会发出一个 OPTION 方法的请求,其中包括以下头部内容:
当服务器接收到OPTION方法请求后,返回以下头部信息:
当OPTION成功请求并收到返回,浏览器将会检查response的头部信息,如果符合条件则正式发起请求,同时缓存此次 Preflighted 请求的结果。反之,如果不符合,那么真正的请求会失败。
JSONP(JSON with padding, 填充式JSON)与 JSON 并无关系,JSONP 的跨域实现主要运用 <script>
不受同域限制的原理,在请求的 URL 后加入一个 callback 参数,该 callback 参数代表服务器需要返回的JS代码的函数名称(eg. <script src="http://localhost?callback=func">
),“func”这个名称将是服务器返回 JS 代码的函数名称(eg. 以php为例,echo "func(123)"
),当 <script>
接收到这段代码的时候,便会运行 func 函数,并把“123”作为数据代进去(前提是你在前面已经写了一个func函数),至此,JSONP 完成。不过 JSONP 有以下缺点:
图像ping 利用 <img>
去访问一个 URL,同时对该 <img>
的 onload
和 onerror
事件进行监听,可以得知请求的成功与失败,但无法获取返回数据,多用于跟踪网页点击次数等。图像ping 有以下缺点:
想要操作 iframe 的内容,那么 iframe 和主页面必须同域。
使用 document.domain 可以修改iframe和主页面的域名为同一个,前提是两个页面处于同一主域名下(eg. p2p.a.com和www.a.com可以设置为a.com),这样就可以操作 iframe 里的 contentDocument 了
使用 location.hash(eg. 将a.com变为a.com#abc不会导致页面刷新),不过由于同域原因,要加多一个和主页面同域的页面才能成功修改主页面的 hash,主页面使用定时器检测 hash 变化。可以查看以下网址了解:
http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html
使用 window.name,同样需要第三个和主页面同域的页面做代理,window.name 可容纳2M的内容。具体方法查看:
http://www.cnblogs.com/rainman/archive/2011/02/21/1960044.html
使用 postMessage,参考
以 node.js 为例,基于 socket.io 可以很容易建立 Web Sockets, HTML5 的 Web Sockets 使用的是 ws://
和 wss://
协议,这样可以减少 http://
和 https://
协议字节级的开销,带宽消耗小。具体实现请查阅Google。
双飞翼布局源自淘宝UED,圣杯布局来自2006年 Matthew Levine 的一篇文章,目的都是为了实现三列布局(中间列自适应宽度,两边分别固定宽度),并且中间列优先加载。两种布局的原理可以应用到两列布局中。
开始之前说一个翻译问题,圣杯布局作者提到发明圣杯布局前的其中一个需求:allow any column to be the tallest
这里应该翻译为:允许任意列高度是最高的,而不是“允许任意列(在 HTML 中位置)在最高”。
在我看来我更喜欢双飞翼布局,用一个 div 标签换来减少多个属性和一个 hack 属性(在 IE 6/7 下圣杯布局需要加入 hack,但是如果 container 触发了 BFC 则该 hack 不用加入,例如 container 使用了 clearfix 或 overflow: hidden)。圣杯布局下需要加入的 hack 是左边的列的 left 属性必须是右边列的宽度的值,在正常浏览器布局下 left 属性的值则是自身的宽度的负值,这里提一个现象,在实现圣杯布局的时候我使用了 clearfix 闭合浮动而不是圣杯布局来源文章中的使用 footer 来清除浮动,导致在 IE 6/7 下会出现的异常布局消失了,我估计是触发了 BFC 的原因(我把 clearfix 去掉后使用了 overflow: hidden 出现同样的效果)。
演示地址:http://www.libinhong.com/demo/Flying
|
|
|
|
演示地址:http://www.libinhong.com/demo/HolyGrails
|
|
|
|