今后遇到的问题和解决方案都会在这里更新作为记录
5月1日
1.实现异步的方式
- 回调函数
- 事件监听
- 发布/订阅
- Promise对象
2.Promise与ES6 generator
promise是为了解决多个回调函数嵌套而提出的。不难想象,如果依次读取多个文件,就会出现多重嵌套。代码不是纵向发展,而是横向发展,很快就会乱成一团,无法管理。这种情况就称为"回调函数噩梦"(callback hell)。它不是新的语法功能,而是一种新的写法,允许将回调函数的横向加载,改成纵向加载。采用Promise,连续读取多个文件,写法如下。
var readFile = require('fs-readfile-promise');
readFile(fileA)
.then(function(data){
console.log(data.toString());
})
.then(function(){
return readFile(fileB);
})
.then(function(data){
console.log(data.toString());
})
.catch(function(err) {
console.log(err);
});
上面代码中,使用了 fs-readfile-promise 模块,它的作用就是返回一个 Promise 版本的 readFile 函数。Promise 提供 then 方法加载回调函数,catch方法捕捉执行过程中抛出的错误。
Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)。
function* gen(x){
var y = yield x + 2;
return y;
}
上面代码就是一个 Generator 函数。它不同于普通函数,是可以暂停执行的,所以函数名之前要加星号,以示区别。
整个 Generator 函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用 yield 语句注明。Generator 函数的执行方法如下。
var g = gen(1);
g.next() // { value: 3, done: false }
g.next() // { value: undefined, done: true }
上面代码中,调用 Generator 函数,会返回一个内部指针(即遍历器 )g 。这是 Generator 函数不同于普通函数的另一个地方,即执行它不会返回结果,返回的是指针对象。调用指针 g 的 next 方法,会移动内部指针(即执行异步任务的第一段),指向第一个遇到的 yield 语句,上例是执行到 x + 2 为止。
换言之,next 方法的作用是分阶段执行 Generator 函数。每次调用 next 方法,会返回一个对象,表示当前阶段的信息( value 属性和 done 属性)。value 属性是 yield 语句后面表达式的值,表示当前阶段的值;done 属性是一个布尔值,表示 Generator 函数是否执行完毕,即是否还有下一个阶段。
5月2日
1.JS异步任务的执行机制
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
2.定时器的执行机制
定时器功能主要由setTimeout()和setInterval()这两个函数来完成,它们的内部运行机制完全一样,区别在于前者指定的代码是一次性执行,后者则为反复执行。以下主要讨论setTimeout()。
setTimeout()接受两个参数,第一个是回调函数,第二个是推迟执行的毫秒数。
console.log(1);
setTimeout(function(){console.log(2);},1000);
console.log(3);
上面代码的执行结果是1,3,2,因为setTimeout()将第二行推迟到1000毫秒之后执行。
如果将setTimeout()的第二个参数设为0,就表示当前代码执行完(执行栈清空)以后,立即执行(0毫秒间隔)指定的回调函数。
setTimeout(function(){console.log(1);}, 0);
console.log(2);
上面代码的执行结果总是2,1,因为只有在执行完第二行以后,系统才会去执行"任务队列"中的回调函数。
总之,setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是说,尽可能早得执行。它在"任务队列"的尾部添加一个事件,因此要等到同步任务和"任务队列"现有的事件都处理完,才会得到执行。
HTML5标准规定了setTimeout()的第二个参数的最小值(最短间隔),不得低于4毫秒,如果低于这个值,就会自动增加。在此之前,老版本的浏览器都将最短间隔设为10毫秒。另外,对于那些DOM的变动(尤其是涉及页面重新渲染的部分),通常不会立即执行,而是每16毫秒执行一次。这时使用requestAnimationFrame()的效果要好于setTimeout()。
需要注意的是,setTimeout()只是将事件插入了"任务队列",必须等到当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数。要是当前代码耗时很长,有可能要等很久,所以并没有办法保证,回调函数一定会在setTimeout()指定的时间执行。
3.替换元素和非替换元素
替换元素是浏览器根据其标签的元素与属性来判断显示具体的内容。img、input、textarea、select、object 等都是替换元素。这些元素都没有实际的内容。替换元素可以增加行框高度,但不增加line-height,内容区高度值 = padding-top + padding-bottom +margin-top + margin-bottom + height。要想替换元素居中,可以设置line-height = height, vertral-align = middle。
大多数元素是不可替换元素,他们将内容直接告诉浏览器,将其显示出来。比如 p的内容、label的内容;浏览器将把这段内容直接显示出来。非替换元素添加padding-top或padding-bottom,不影响行框高度,但内容区高度会变化,margin-top,margin-bottom对行框没有任何影响。
非替换行内元素的行框高由line-height
确定,替换行内元素的行框高由height
,margin
,padding
,border
决定
4.CSS3的可继承属性和不可继承属性
不可继承的:display、margin、border、padding、background、height、min-height、max-height、width、min-width、max-width、overflow、position、left、right、top、bottom、z-index、float、clear、table-layout、vertical-align、page-break-after、page-bread-before和unicode-bidi。
所有元素可继承:visibility和cursor。
内联元素可继承:letter-spacing、word-spacing、white-space、line-height、color、font、font-family、font-size、font-style、font-variant、font-weight、text-decoration、text-transform、direction。
终端块状元素可继承:text-indent和text-align。
列表元素可继承:list-style、list-style-type、list-style-position、list-style-image。
5.margin:0 auto与text-align:center的区别
1.text-align:center 设置文本或img标签等一些内联对象(或与之类似的元素)的居中
2.margin:0 auto 设置块元素(或与之类似的元素)的居中。
5月3日
1.Cookie的格式及组成
Set-Cookie: NAME=VALUE;Expires=DATE;Path=PATH;Domain=DOMAIN_NAME;SECURE
这是每一个Cookie均必须有的部分。NAME是该Cookie的名称,VALUE是该Cookie的值。在字符串“NAME=VALUE”中,不含分号、逗号和空格等字符。
Expires=DATE:Expires变量是一个只写变量,它确定了Cookie有效终止日期。该属性值DATE必须以特定的格式来书写:星期几,DD-MM-YY HH:MM:SS GMT,GMT表示这是格林尼治时间。反之,不以这样的格式来书写,系统将无法识别。该变量可省,如果缺省时,则Cookie的属性值不会保存在用户的硬盘中,而仅仅保存在内存当中,Cookie文件将随着浏览器的关闭而自动消失。
Domain=DOMAIN-NAME:Domain该变量是一个只写变量,它确定了哪些Internet域中的Web服务器可读取浏览器所存取的Cookie,即只有来自这个域的页面才可以使用Cookie中的信息。这项设置是可选的,如果缺省时,设置Cookie的属性值为该Web服务器的域名。
Path=PATH:Path属性定义了Web服务器上哪些路径下的页面可获取服务器设置的Cookie。一般如果用户输入的URL中的路径部分从第一个字符开始包含Path属性所定义的字符串,浏览器就认为通过检查。如果Path属性的值为“/”,则Web服务器上所有的WWW资源均可读取该Cookie。同样该项设置是可选的,如果缺省时,则Path的属性值为Web服务器传给浏览器的资源的路径名。
可以看出我们借助对Domain和Path两个变量的设置,即可有效地控制Cookie文件被访问的范围。
Secure:在Cookie中标记该变量,表明只有当浏览器和Web Server之间的通信协议为加密认证协议时,浏览器才向服务器提交相应的Cookie。当前这种协议只有一种,即为HTTPS。
5月7日
关于npm install
npm install express
默认会安装express的最新版本,也可以通过在后面加版本号的方式安装指定版本,如npm install express@3.0.6npm install <name> -g 将包安装到全局环境中
但是代码中,直接通过require()的方式是没有办法调用全局安装的包的。全局的安装是供命令行使用的,就好像全局安装了vmarket后,就可以在命令行中直接运行vm命令npm install <name> --save
安装的同时,将信息写入package.json中项目路径中如果有package.json文件时,直接使用npm install方法就可以根据dependencies配置安装所有的依赖包,这样代码提交到github时,就不用提交node_modules这个文件夹了。
5月8日
关于npm、spm、bower 这三个包管理器
- NPM针对node模块,原生支持commonJS,而前端模块除非该管理器自己定了,否则规范是无法统一的。即便规定了commonJS,那么必定会有配套工具打包来实现实际的运转。
- 处理依赖的方式不同。NPM针对的node模块,它的依赖是树状的。项目中用到的A,B,C三个模块,他们可以分别依赖不同版本的lodash,而互不影响。但是前端模块除非做了很好的模块隔离(如实现了commonJS,并能很好地进行打包,即便如此,前端环境的特殊性也无法忍受相同模块的不同版本并存。比如页面中引入两个版本的jQuery,代码数据传输X2),否则一般的依赖都是扁平的。
5月9日
关于onchange事件的触发时机
当焦点离开时才出发onchange事件
5月11日
document.ready与window.onload区别
在Jquery里面,我们可以看到两种写法:$(function(){}) 和$(document).ready(function(){})这两个方法的效果都是一样的,都是在dom文档树加载完之后执行一个函数(注意,这里面的文档树加载完不代表全部文件加载完)。而window.onload是在dom文档树加载完和所有文件加载完之后执行一个函数。也就是说$(document).ready要比window.onload先执行。
5月18日
为什么JS是单线程
JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。
5月19日
JQuery中deferred方法的总结
(1) $.Deferred() 生成一个deferred对象。
(2) deferred.done() 指定操作成功时的回调函数
(3) deferred.fail() 指定操作失败时的回调函数
(4) deferred.promise() 没有参数时,返回一个新的deferred对象,该对象的运行状态无法被改变;接受参数时,作用为在参数对象上部署deferred接口。
(5) deferred.resolve() 手动改变deferred对象的运行状态为"已完成",从而立即触发done()方法。
(6)deferred.reject() 这个方法与deferred.resolve()正好相反,调用后将deferred对象的运行状态变为"已失败",从而立即触发fail()方法。
(7) $.when() 为多个操作指定回调函数。
除了这些方法以外,deferred对象还有二个重要方法,上面的教程中没有涉及到。
有时为了省事,可以把done()和fail()合在一起写,这就是then()方法。
5月28日
req.param,req.query,req.body的区别
req.param获取pathinfo中的参数/api/users/{id}
req.query获取查询参数/api/user?name=xky
req.body获取form中提交的参数
6月1日
Gulp和Grunt的区别
Gulp和Grunt的工作方式很不一样。Grunt不使用数据流,而是使用文件,对文件执行单个任务然后保存到新的文件中,每个任务都会重复执行所有进程,文件系统频繁的处理任务会导致Grunt的运行速度比Gulp慢。
6月4日
flexbox不定宽高的水平垂直居中
.parent{ justify-contentL:center //子元素水平居中 align-items:center //子元素垂直居中 display:webkit-flex
6月6日
伪元素与伪类的区别
CSS
伪类用于向某些选择器添加特殊的效果。
CSS
伪元素用于将特殊的效果添加到某些选择器。
6月7日
使用负的 nth-child 选择项目
li { display: none; } /* select items 1 through 3 and display them */ li:nth-child(-n+3) { display: block; }
6月11日
css3 box-sizing属性
box-sizing属性可以为三个值之一:content-box(default),border-box,padding-box。
content-box,border和padding不计算入width之内
padding-box,padding计算入width内
border-box,border和padding计算入width之内,其实就是怪异模式了~
6月13日
模糊文本
原文链接:http://caibaojian.com/useful-css-tips.html
简单但很漂亮的文本模糊效果,简单又好看!
//code from http://caibaojian.com/useful-css-tips.html .blur { color: transparent; text-shadow: 0 0 5px rgba(0,0,0,0.5); }
6月16日
实参和形参
var add = function (a,b) { console.log(arguments.length);//3,表示实参长度 console.log(arguments.callee.length);//2,表示形参长度 }; add(1,2,3);
new function
var a = function () {}; console.log(typeof a);//function var b = new function () {}; console.log(typeof b);//object var c = new Function (); console.log(typeof c);//function new function 是一个JavaScript中用户自定义的对象 var obj = function (name) { this.name = name; }; var b = new obj('xiaokunyu'); console.log(b.name);
js中的false和true
除了false,null,undefined
,空字符串''
,数字0和NaN
以外,其他所有值都被当做是真,包括true
,字符串""
里包含的值,以及所有对象。
6月22日
valueOf() 和 toString()
valueOf()和toString()方法是所有ECMAScript对象拥有的内置方法。操作对象时,valueOf()和toString()会被隐式的调用。
//valueOf()
console.log(Object.valueOf());//[Function: Object]
console.log(Object.prototype.valueOf());//{}
var boo = new Boolean(1);
console.log(boo.valueOf());//true
var bar = Boolean(0);
console.log(bar.valueOf());//false
var str = String("trigkit4");
console.log(str.valueOf());//trigkit4
console.log(null.valueOf());//TypeError
console.log(undefined.valueOf());//TypeError
//toString()
console.log(Object.prototype.toString());//[object Object]
console.log(Object.toString());//function Object() { [native code] }
Object.prototype.toString.call(null);//[object Null]
Object.prototype.toString.call(undefined);//[object Undefined]
{a: 'b'}.toString();//[object Object]
valueOf()方法的目的是将对象转换成最有意义的原始值([[PrimitiveValue]])。即ECMAScript的5种基本类型中的三种,布尔值、数字、字符串。
当valueOf方法被调用时,会调用内置的ToObject,并将this作为参数传进去。ToObject检测会根据参数类型进行数值的转换:
Undefined - 抛出TypeError异常
Null - 抛出TypeError异常
Boolean - 创建一个Boolean对象,调用ToBoolean生成[[PrimitiveValue]]
Number - 创建一个Number对象,调用ToNumber生成[[PrimitiveValue]]
String - 创建一个String对象,调用ToString生成[[PrimitiveValue]]
Object - 对象本身
ECMAScript对象的大多数操作的转换结果是字符串,这两个方法的结果是相同的。但是如果操作的对象为Number、Boolean或者Date,结果就不同了。
var foo = {
toString: function () {
return "foo";
},
valueOf: function () {
return 5;
}
};
console.log(foo + "bar"); // 5bar
console.log([foo, "bar"].join("")); // foobar
在这个上下文环境中,我们使用"+"操作符来使字符串连接,但是,foo并没有使用toString来转换成字符串,它使用valueOf转换成一个number,这并不是我们想要的,
但它是如何工作的,这是+运算符的算术和字符串连接超载的副作用。"+"操作符有一个明确的处理过程:
1.评估左手侧,并得到该值。
2.评估右手侧,并获得该值。
3.同时在左手和右手侧调用ToPrimitive(无提示)
4.如果任何原始值是一个字符串,然后跳到7。
5.在这两个值调用ToNumber。
6.返回值的总和。
7.在这两个值调用toString。
8.返回的值连接起来
6月23日
cookie的取值
cookie
可以跨越一个域名下的多个网页,但不能跨越多个域名使用。
document.cookie = “user = 值;expires = 过期时间;path = 路径访问;
domain = 域名访问;secure = 安全的https限制通信"
cookie的创建方式
设置cookie
我们一般都封装成一个函数:
function addCookie(sName,sValue,day) { var expireDate = new Date(); expireDate.setDate(expireDate.getDate()+day);; //设置失效时间 document.cookie = escape(sName) + '=' + escape(sValue) +'; expires=' + expireDate.toGMTString();6 //escape()汉字转成unicode编码,toGMTString() 把日期对象转成字符串 }
删除cookie
为了删除一个cookie
,可以将其过期时间设定为一个过去的时间,例如:
//获取当前时间
var date=new Date(); //将date设置为过去的时间 date.setTime(date.getTime()-10000); //将userId这个cookie删除 document.cookie="userId=828; expires="+date.toGMTString();
给cookie设置终止日期
到现在为止,所有的cookie
都是单会话cookie
,即浏览器关闭后这些cookie
将会丢失,事实上这些cookie
仅仅是存储在内存中,而没有建立相应的硬盘文件。
在实际开发中,cookie
常常需要长期保存,例如保存用户登录的状态。这可以用下面的选项来实现:
document.cookie="userId=828; expiress=GMT_String";
其中GMT_String
是以GMT
格式表示的时间字符串,这条语句就是将userId
这个cookie
设置为GMT_String
表示的过期时间,超过这个时间,cookie
将消失,不可访问。例如:如果要将cookie
设置为10天后过期,可以这样实现:
<script language="JavaScript" type="text/javascript"> //获取当前时间 var date=new Date(); var expiresDays=10; //将date设置为10天以后的时间 date.setTime(date.getTime()+expiresDays*24*3600*1000); //将userId和userName两个cookie设置为10天后过期 document.cookie="userId=828; userName=hulk; expires="+date.toGMTString(); </script>
对象和函数可以如数组一样,用属性名或方法名作为下标来访问:
6月29日
String 原型方法的扩展
//公共正则表达式处理函数
String.prototype.Regular = function(reg){ var result = true; if(this.length > 0){ if(!reg.test(this)){ result = false; } } return result; } //.trim()方法 String.prototype.trim = function () { return this.replace(/(^\s*)|(\s*$)/g,''); };
^
表示字符串必须以后面的规则开头,而(^\s*)
表示的就是以0个空格或者多个空格开头,后面的(\s*$)
的意思就是, 以0个空格或者多个空格结尾。
//判断输入内容是否为空
String.prototype.isNull = function(){ return this.trim().length == 0 ? true : false; } //判断输入的字符是否为英文字母\数字\下划线 String.prototype.isVersion = function(){ var reg = /^([a-zA-Z_])([a-zA-Z0-9_.])*$/; return this.Regular(reg); } // 判断输入的字符串,不包括单引号 String.prototype.isString = function(){ var reg = /^[^']*$/; return this.Regular(reg); } //判断输入的字符是否为英文字母 String.prototype.isLetter = function(){ var reg = /^[a-zA-Z]+$/; return this.Regular(reg); }
7月2日
tranform,transation,transate的区别
7月4日
重定向页面的方法
// 类似HTTP重定向的行为 window.location.replace("http://stackoverflow.com"); // 类似点击一个链接的行为 window.location.href = "http://stackoverflow.com";
7月7日
css3 box-sizing属性
box-sizing属性可以为三个值之一:content-box(default),border-box,padding-box。
content-box,border和padding不计算入width之内
padding-box,padding计算入width内
border-box,border和padding计算入width之内,其实就是怪异模式了~
7月10日
array filter
function remove(arr, item) { return arr.filter(function(x) { return x !== item; }); }
关于eval
可以直接执行字符串中的JS
7月11日
数组清除重复项
这是另外一道题目,数组里有重复项,要怎么清除。一查我再掩面而泣,原来js里就带了filter就可以干这活。代码如下:
myArray.filter(function(elem, pos,self){return self.indexOf(elem)== pos;})
filter是过滤的意思,filter通过一个函数的参数来选择什么项需要被filter掉,函数返回true保留,false干掉。
函数参数带三个参数,第一个elem是这一项元素,第二个pos是这一项所在的位置,第三个self指的是执行filter的数组。那么,你看,巧妙吗:self.indexOf(elem) 是指这个项目在数组中的位置,位置是第一个,也就是说同样的项目在第一位和第5位都出现了,他返回的是0,而此时pos还是4,所以通过self.indexOf(elem) == pos 能判断出这一项是不是重复出现的项,如果是(返回false),则干掉它。
Array map
map()对数组的每个元素进行一定操作(映射)后,会返回一个新的数组
7月12日
JS数组实现堆栈的方法
shift:从集合中把第一个元素删除,并返回这个元素的值。
unshift: 在集合开头添加一个或更多元素,并返回新的长度
push:在集合中添加元素,并返回新的长度
pop:从集合中把最后一个元素删除,并返回这个元素的值。
7月14日
如何用两个栈实现一个队列
入队时,将元素压入s1。
出队时,判断s2是否为空,如不为空,则直接弹出顶元素;如为空,则将s1的元素逐个“倒入”s2,把最后一个元素弹出并出队。
这个思路,避免了反复“倒”栈,仅在需要时才“倒”一次。
7月16日
JS的各种属性与方法
http://www.jb51.net/article/53960.htm
元素节点,属性节点和文本节点
http://www.cnblogs.com/dh616854836/archive/2011/08/14/2138038.html
7月19日
节点信息
每个节点都拥有包含着关于节点某些信息的属性。这些属性是:
- nodeName(节点名称)
- nodeValue(节点值)
- nodeType(节点类型)
7月21日
git fetch和git pull的区别
git pull:相当于是从远程获取最新版本并merge到本地 git fetch:相当于是从远程获取最新版本到本地,不会自动merge
7月22日
响应式与自适应的区别
响应式与自适应的原理是相似的,都是检测设备,根据不同的设备采用不同的css,而且css都是采用的百分比的,而不是固定的宽度,不同点是响应式的模板在不同的设备上看上去是不一样的,会随着设备的改变而改变展示样式,而自适应不会,所有的设备看起来都是一套的模板,不过是长度或者图片变小了,不会根据设备采用不同的展示样式,流式就是采用了一些设置,当宽度大于多少时怎么展示,小于多少时怎么展示,而且展示的方式向水流一样,一部分一部分的加载,静态的就是采用固定宽度的了。
8月12日
getElementsByTagName()的返回值问题
返回值是DOM对象而不是数组。可以通过
Array.prototype.slice.call()
来转化为数组
function定义的对象有一个prototype属性,使用new生成的对象就没有这个prototype属性。
8月13日
关于this的指向
当函数作为方法调用时,this指向调用该方法的对象, 当函数作为嵌套函数调用时, this指向全局对象(非严格模式下)或者undefined(严格模式)而不是其外包函数的上下文
em和rem
em相对于父级font.rem相对于html跟元素的font
defer与async
原文链接:http://caibaojian.com/jsload.html
带有 defer
属性的<script>
标签可以放置在文档的任何位置。对应的 JavaScript 文件将在页面解析到<script>
标签时开始下载,但不会执行,直到 DOM 加载完成,即onload
事件触发前才会被执行。当一个带有 defer
属性的 JavaScript 文件下载时,它不会阻塞浏览器的其他进程,因此这类文件可以与其他资源文件一起并行下载。
原文链接:http://caibaojian.com/jsload.html
数字转为数组:
'' + (Math.floor(Math.random() * width) + start)
,在有 async
的情况下,JavaScript 脚本一旦下载好了就会执行,所以很有可能不是按照原本的顺序来执行的。如果 JavaScript 脚本前后有依赖性,使用 async
就很有可能出现错误。
8月16日
通用判断类型的方法
Object.prototype.toString()
在toString方法被调用时,会执行下面的操作步骤:
1. 获取this对象的[[Class]]属性的值。
2. 计算出三个字符串"[object ", 第一步的操作结果Result(1), 以及 "]"连接后的新字符串。
3. 返回第二步的操作结果Result(2)。
[[Class]]是一个内部属性,所有的对象(原生对象和宿主对象)都拥有该属性.在规范中,[[Class]]是这么定义的:
内部属性 描述
[[Class]] 一个字符串值,表明了该对象的类型。
其过程简单说来就是:1、获取对象的类名(对象类型)。2、然后将[object、获取的类名、]组合并返回。
8月20日
单页面应用
http://www.tuicool.com/articles/IvyYNb