友情提示:本文仅mark几个常用的新特性,详细请参见:ES6入门 - ryf

碎片

var VS let VS const

  • var:声明全局变量,
  • let:声明块级变量,即局部变量
  • const:声明常量,块级作用域,不可修改且必须初始化

将一个对象彻底冻结为常量的方法

var constantize = (obj) => {
// 冻结对象本身
Object.freeze(obj);
// 冻结对象的属性
Object.keys(obj).forEach( (key, i) => {
if ( typeof obj[key] === 'object' ) {
constantize( obj[key] );
}
});
};  

ES6声明变量的方法,除上述外,还支持:class、import、function。

Number.isNaN() & Number.isFinite()  

该两者仅对数值有效:

  • Number.isNaN():判断一个数值是否为NaN,利用NaN是唯一不等于自身的值,用于isNaN()判断
  • Number.isFinite():表示某个数值是否为正常的数值(即,非infinity),Infinity、-Infinity、NaN和undefined返回false,其余均返回true

注意与传统的全局方法isFinite()和isNaN()的区别,传统方法先调用Number()将非数值的值转为数值,再进行判断。

同理,Number.parseInt(), Number.parseFloat()优先使用。

新增Number.EPSILON表示极小量,表示 1 与大于 1 的最小浮点数之间的差。

function isTrueWithinErrorMargin (left, right) {
return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2);
}

新增Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER分别表示安全的极大值和极小值。

Symbol

JS 的第7种数据类型,独一无二的特性:

  • 用于扩展对象属性名
  • 定义常量

提供几个常用方法

  • Symbol()
  • Symbol.for()
  • Symbol.keyfor()

${}

模版字符串(template string)语法,配合反引号``使用

  • 换行
  • 表达式嵌入:占位符(使用 <%...%> 放置 JavaScript 代码,使用 <%= ... %> 输出 JavaScript 表达式。)
  • 支持嵌套

标签模版

函数调用的一种特殊形式:fun`xxx`。

可过滤 HTML 字符串,防止用户输入恶意内容(特殊字符转义)

function toSaferHTML(templateData) {
let s = templateData[0];
for (let i = 1; i < arguments.length; i++) {
let arg = String(arguments[i]); // Escape special characters in the substitution.
s += arg.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">"); // Don't escape special characters in the template.
s += templateData[i];
}
return s;
} let sender = '<script>alert("abc")</script>'; // 恶意代码
let message = toSaferHTML`<p>${sender} has sent you a message.</p>`;
// <p><script>alert("abc")</script> has sent you a message.</p>

注:模板处理函数的第一个参数(模板字符串数组),还有一个 raw 属性,用于保存转义后的原字符串。

支持多语言处理。

...

扩展运算符,基于 for...of,将一个数组转为参数序列,或将实现了 Iterator 接口的对象转化为真正的数组。

  • 取代apply()方法
  • 复制数组(深拷贝)或合并数组(浅拷贝)
  • 配合解构赋值:扩展运算符可以识别四字节的Unicode字符的长度

注意,没有实现 Iterator 接口的对象可以使用Array.from

  • 类似数组的对象:(1)DOM 操作返回的 NodeList 集合;(2)函数内部的arguments对象
  • 可遍历的对象

提供2种字符串长度方法

[1]. [...str].length
[2]. Array.from(str).length 

Object.assign

将源对象(source)的所有可枚举属性,复制到目标对象(target)。(浅拷贝)

  • undefined和null不能作为第一个参数
  • 只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)

使用场景

  • 为对象添加属性/方法
  • 克隆/合并对象
  • 为属性指定默认值

Object.getOwnPropertyDescriptor

获取对象属性的描述对象,其中属性enumerable表示可枚举性。以下只对enumerable=true的对象有效

  • for...in循环:只遍历对象自身的和继承的可枚举的属性
  • Object.keys():返回对象自身的所有可枚举的属性的键名
  • JSON.stringify():只串行化对象自身的可枚举的属性
  • Object.assign(): 忽略enumerablefalse的属性,只拷贝对象自身的可枚举的属性

Object.getOwnPropertyDescriptors

基于Object.getOwnPropertyDescriptor实现,返回指定对象所有自身属性(非继承属性)的描述对象。

  • 解决Object.assign()无法正确拷贝get属性和set属性的问题
  • 配合Object.create方法,将对象属性克隆到一个新对象(浅拷贝)
  • 实现 Mixin(混入)模式
//克隆 方法1
const clone = Object.create(
Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj)
);
//方法2
const clone2 = Object.assign(
Object.create(Object.getPrototypeOf(obj)),
obj
);

属性遍历

  • for...in
  • Object.keys()
  • Object.getOwnPropertyNames():返回一个数组,包含对象自身的所有属性的键名
  • Object.getOwnPropertySymbols():返回一个数组,包含对象自身的所有 Symbol 属性的键名
  • Reflect.ownKeys():返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举

建议,尽量不要用for...in循环,而用Object.keys()代替。

此外,for...in只能获得对象的键名,不能直接获取键值,而for...of允许遍历获得键值。

Iterator & for...of

为不同的数据结构提供统一的访问机制,任何数据结构只要部署了Iterator接口:

  • 支持遍历(for...of)操作
  • 使用扩展运算符,将其转为数组

本质是:数据结构部署Symbol.iterator属性

遍历器接口(Iterable)、指针对象(Iterator)和next方法返回值的模版描述如下

interface Iterable {
[Symbol.iterator]() : Iterator,
} interface Iterator {
next(value?: any) : IterationResult,
} interface IterationResult {
value: any,
done: boolean,
}

原生具备 Iterator 接口的数据结构:

Array
Map
Set
String
TypedArray
函数的 arguments 对象
NodeList 对象

默认调用遍历器的场景

  • for...of
  • 解构赋值
  • ...
  • yield*:其后面跟一个可遍历的结构,默认调用该结构的遍历器接口
  • Array.from(),Promise.all/race()

扩展应用

  • String

将遍历器转换为数组,提供2种方法:

[...str.matchAll(regex)]
Array.from(str.matchAll(regex));

其中,matchAll() 用于一次性取出所有匹配结果,返回一个遍历器。  

Set & Map

ES6在原有的集合数据结构(数组Array和对象Object)的基础上,新增MapSet

  • Set:类似数组,值唯一
  • Map:类似(键值对集合的)对象,将"字符串-值"结构的Object扩展到"值-值"结构的Map
  • WeakSet:不可遍历,成员只能是对象
  • WeakMap:不可遍历

很重要:遍历顺序就是插入顺序。支持遍历 for...of 和 forEach。

其中,forEach 方法的

  • 第一个参数回调函数的参数依次为:(value, key, map)
  • 第二个参数用于绑定this,指向某个对象

Set

[1]. 数组去重

function dedupe(array) {
return Array.from(new Set(array));
}

[2]. 交并差集运算

若想改变Set本身,提供如下2种方法

// 方法一:利用原 Set 结构映射出一个新的结构,然后赋值给原来的 Set 结构
let set = new Set([1, 2, 3]);
set = new Set([...set].map(val => val * 2));
// 方法二:利用Array.from方法
let set = new Set([1, 2, 3]);
set = new Set(Array.from(set, val => val * 2));

Map

关于Map与其他数据结构的转换,可参见:http://es6.ruanyifeng.com/#docs/set-map

解构赋值

从数组和对象中提取值,对变量进行赋值:(模式匹配)

  • 只要等号右边的值不是对象或数组,就先将其转为对象
  • 实现了Iterator接口的数据结构,可以采用数组形式的解构赋值
  • 由于undefined和null无法转为对象,所以对其解构赋值,会报错
  • 解构赋值尽量不适用圆括号()

支持默认值,前提是对象的属性值/数组成员严格等于undefined。若数组成员是null,默认值不会生效。

除数组和对象,字符串也支持解构赋值。

应用场景

  • 交换变量的值
  • 从函数返回多个值
  • 函数参数的定义、默认值
  • 提取json数据
  • 利用for...of遍历map结构

[1]. 在函数形参使用解构赋值

// 写法一
function m1({x = 0, y = 0} = {}) {
return [x, y];
}
// 写法二
function m2({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
  • 写法一:函数参数的默认值是空对象,但是设置了对象解构赋值的默认值
  • 写法二:函数参数的默认值是一个有具体属性的对象,但是没有设置对象解构赋值的默认值

推荐写法一,因为在函数体中实际使用的左边的x和y。 

箭头函数

箭头函数可以让this指向固定化,总是指向函数定义生效时所在的作用域,而不是指向运行时所在的作用域,这种特性很有利于封装回调函数。

s1 = 0;  s2 = 0;
function Timer() {
this.s1 = 0; this.s2 = 0;
// 箭头函数
setInterval(() => this.s1++, 1000);
// 普通函数
setInterval(function () {
this.s2++;
}, 1000);
} var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 3200); // 3
setTimeout(() => console.log('s2: ', timer.s2), 3200); // 0
setTimeout(() => console.log('s11: ', this.s1), 3200); // 0
setTimeout(() => console.log('s22: ', this.s2), 3200); // 3

箭头函数自动绑定this,可以减少对this的显式绑定(callapplybind)。

::双冒号运算符(函数绑定运算符),可以用来取代callapplybind调用。

foo::bar(...arguments);  等同于  bar.apply(foo, arguments);  

注意点

  • 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象
  • 不可以当作构造函数,即:不可以使用new命令 
  • 不可以使用yield命令,即:箭头函数不能用作 Generator 函数
  • 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替

尾调用 & 尾递归

尾调用:某个函数的最后一步是调用另一个函数

function f(x){
return g(x); //(1)return (2)无其他计算
}

尾递归基于尾调用,相对节省内存,不会发生栈溢出。

相关示例,可参考:阶乘或Fibonacci 数列.

注意,尾调用优化,仅在严格模式下有效。

Proxy & Reflect

Proxy:修改某些操作的默认行为,可以进行数据验证

关于 Proxy 支持的拦截操作,具体参见:http://es6.ruanyifeng.com/#docs/proxy

其中,apply用于拦截如下操作:

  • 函数调用
  • call、apply
  • Reflect.apply

Reflect:将Object对象上的方法迁移到Reflect对象上

关于Reflect对象的方法与Proxy对象的方法一一对应,具体参见:http://es6.ruanyifeng.com/#docs/reflect

建议用 Reflect.xxx 代替 Object.xxx

综上,Proxy 对象和 Reflect 对象联合使用,前者拦截操作,后者完成默认行为。

Promise对象

引出

  • 回调地狱(callback hell)
  • 多个异步回调难以维护和控制的问题

设计思想:所有异步任务都返回一个 Promise 实例。(异步操作同步化)

Promise 实质上是一个构造函数。

var p = new Promise(f1);
p.then(f2);

回调函数f1完成后,执行回调函数f2。(添加状态改变时的回调函数通过then()方法)

Promise 对象通过自身的状态,来控制异步操作。

  • 异步操作未完成(pending)
  • 异步操作成功(fulfilled)
  • 异步操作失败(rejected)

同时,只有异步操作的结果才会改变其状态,Promise 实例的状态变化只可能发生一次:

  • 异步操作成功,Promise 实例传回一个值(value),状态变为 fulfilled
  • 异步操作失败,Promise 实例抛出一个错误(error),状态变为 rejected
// resolve 和 reject 均由 JavaScript 引擎提供,无需自己实现
var p = new Promise(function (resolve, reject) {
// ...
if (/* 异步操作成功 */){
resolve(value);
} else { /* 异步操作失败 */
reject(new Error());
}
});
  • resolve:将Promise实例的状态从“未完成”变为“成功”(pending-->fulfilled),在异步操作成功时调用,并将异步操作的结果作为参数传出
  • reject:将Promise实例的状态从“未完成”变为“失败”(pending-->rejected),在异步操作失败时调用,并将异步操作的错误作为参数传出

注意:

  • Promise 的回调函数属于异步任务,会在同步任务之后执行。
  • Promise 的回调函数不是正常的异步任务,而是微任务(microtask) 

正常任务追加到下一轮事件循环,微任务追加到本轮事件循环。所以,微任务的执行时间一定早于正常任务。

setTimeout(function() {
console.log(1);
}, 0); new Promise(function (resolve, reject) {
resolve(2);
}).then(console.log); console.log(3); // 3 2 1

Promise对象还有其他特性(可以看作是缺点):

  • Promise 对象新建后就会立即执行,无法取消Promise
  • Promise 内部的错误不会影响到 Promise 外部的代码(Promise 会吃掉错误),也可以通过设置回调函数将错误信息抛出
  • 代码冗余,all then()...

静态方法

  • Promise.all():与
  • Promise.race():或
  • Promise.resolve():将现有对象转为立即resolved的Promise对象
  • Promise.reject():返回一个新的Promise实例,该实例的状态为rejected,回调立即执行

Promise.resolve()与Promise.reject()略有不同,Promise.reject()会将参数原封不动地传出。

新的Promise.try()用于统一管理同步和异步代码,统一用promise.catch()捕获所有同步和异步的错误

Promise.try(database.users.get({id: userId}))
.then(...)
.catch(...)

参考:Promise对象ES6 - Promise - ryfeng

Generator函数

遍历器对象生成函数,可以暂停函数执行,返回任意表达式的值

  • function*:
  • yield:产出,暂停标志

调用Generator函数,返回一个遍历器对象,代表Generator函数的内部指针,可以通过next()依次遍历Generator函数内部的每一个状态(异步操作的容器)。

  • 异步操作同步化表达
  • 为任意对象部署 Iterator 接口
  • 作为数据结构,提供类似数组的接口
  • 控制流管理:项目拆分成任务,任务拆分成步骤,依次执行
  • 状态机(容器)
  • 协程(coroutine)

注意,返回的遍历器对象,其Symbol.iterator属性是其自身

function* gen(){...}
var g = gen();
g[Symbol.iterator] === g

遍历器对象是Generator函数的实例,继承其原型上的方法,但是this对象无法访问。若想访问:

// 将遍历器对象绑定到Generator函数的原型
var gen = Gen.call(Gen.prototype);  

若想应用new命令,对外封装一层即可

function F() {
return Gen.call(Gen.prototype);
}
// f即遍历器对象
F f = new F();

for...of

支持自动遍历Generator函数时生成的Iterator对象。

注意,不会遍历到return语句,扩展运算符、解构赋值和Array.from()亦是。

利用for...of循环,可以写出遍历任意对象(object)的方法。通过Generator函数为对象加上这个接口

function* objectEntries() {
let propKeys = Object.keys(this); for (let propKey of propKeys) {
yield [propKey, this[propKey]];
}
} let obj= { first: 'Jane', last: 'Doe' };
obj[Symbol.iterator] = objectEntries; for (let [key, value] of objectEntries(obj)) {
console.log(`${key}: ${value}`);
}

重点理解下述3个原型方法:

Generator.prototype.next()

  • next方法可以带一个参数,该参数重写上一个yield表达式的返回值(yield表达式默认无返回值或undefined)
  • 第一次执行next方法,等同于启动执行Generator函数的内部代码

Generator.prototype.throw()

  • Generator函数体内或外抛出的错误gen.throw(),会优先被Generator体内的try...catch捕获
  • 注意遍历器对象的throw()方法和throw命令的不同
  • throw方法抛出的错误要被内部try...catch捕获,前提是必须至少执行过一次next方法,,否则只能被外部try...catch捕获
  • throw方法被捕获后,会附带执行一次next方法,返回下一条yield表达式
  • Generator函数体内的错误未捕获到,会中断Generator函数体内的后续代码 

Generator.prototype.return()

  • 返回给定的值,终结执行Generator函数
  • 优先级低于finally代码块
next(): 将yield表达式替换成一个值
throw(): 将yield表达式替换成一个throw语句
return(): 将yield表达式替换成一个return语句  

yield*

在一个Generator函数A里面执行另一个Generator函数B。

场景:递归

若B中有return语句,通过以下形式获取返回值

var value = yield* B()

异步应用

异步调用方式

  • 发布/订阅(事件监听)
  • 回调函数
  • Promise对象
  • Generator函数:协程

协程

Generator函数是协程在ES6的实现,可以理解为Generator函数是协程的实例

最大特点就是可以交出函数的执行权(暂停函数执行和恢复执行)

  • 函数体内、外的数据交换
  • 错误处理机制

自动执行机制:接收和交还程序的执行权(当异步操作有了结果,自动交回执行权)

  • 回调函数:将异步操作包装成 Thunk 函数,在回调函数里面交回执行权
  • Promise对象:将异步操作包装成 Promise 对象,用then方法交回执行权

Thunk函数

自动执行Generator函数的一种方法。

  • yield:将程序的执行权移出 Generator 函数
  • thunk:将执行权交还给 Generator 函数

懒执行,传名调用的实现策略,用临时函数(Thunk函数)替换某个表达式。在JavaScript中,是将多参数(某个参数是回调函数)函数fn,替换成一个只接受回调函数作为参数的单参数函数。

// Thunk函数转换器
const Thunk = function(fn) {
return function (...args) {
return function (callback) {
return fn.call(this, ...args, callback);
}
};
};  

提供Thunk函数转换工具:Thunkify 模块

无需编写Generator函数的自动执行器,而且其检查机制,确保回调函数只运行一次。使用前提是Generator函数的yield命令后面,只能是Thunk函数。

// 引入
var thunkify = require('thunkify');
// 转换
var thunkFun= thunkify(fn);

co模块

自动执行Generator函数的另一种方法,基于Promise对象的自动执行器。

co函数接收Generator函数作为参数,返回Promise对象,支持then方法执行回调函数。

// 引入
var co = require('co');
// 自动执行
co(gen).then(...);

本质上封装了两种自动执行器(Thunk 函数和 Promise 对象),使用 co 的前提条件是,Generator函数的yield命令后面,只能是 Thunk 函数或 Promise 对象。 

而且,co函数支持并发操作:把并发的操作放在数组或对象里,跟在yield命令后面

参考 :Generator - ruanyifeng

以上,使Generator支持异步操作,即yield命令后是异步方法,则:该方法只能返回一个Thunk函数或者一个Promise对象。

async函数

  • async:表示函数里有异步操作
  • await:表示紧跟在后面的表达式需要等待结果

Generator函数的语法糖:对Generator函数和自动执行器的封装

相比Generator函数:( *和yield --> async和await )

  • 内置(自动)执行器
  • 立即返回Promise对象,支持then方法执行回调函数。
  • 语义清晰,适应性广

async函数可以看作是将多个异步操作封装成一个Promise对象,await命令是内部then()方法的语法糖。

关于3者的比较,可参见:async函数-5

务必注意,不能在普通函数中使用await。但是 esm 模块加载器支持顶层await,即await命令可以不放在async函数里面,直接使用

// 顶层 await 的写法
const res = await fetch('google.com');
console.log(await res.text()); 

常见形式:

// 函数声明
async function foo() {}
// 函数表达式
const foo = async function () {};
// 箭头函数
const foo = async () => {}; // 对象的方法
let obj = {
async foo() {}
};
obj.foo().then(...) // Class 的方法
class Storage {
constructor() {
this.cachePromise = caches.open('avatars');
}
async getAvatar(name) {
const cache = await this.cachePromise;
return cache.match(`/avatars/${name}.jpg`);
}
}
const storage = new Storage();
storage.getAvatar('jake').then(…);

错误处理机制

async函数内部抛出错误,会导致返回的Promise对象变为reject状态,同时中断async函数的执行,若不中断:

  • try...catch
  • await Promise(...).catch()

抛出的错误对象会被catch方法回调函数接收到。

并发

互不影响相互独立的2个异步操作同时执行

let [foo, bar] = await Promise.all([getFoo(), getBar()]);

场景:并发拉数据

async function pullDataFeomUrl(urls) {
// 并发读取远程URL
const textPromises = urls.map(async url => {
const response = await fetch(url);
return response.text();
}); // 按次序输出
for (const textPromise of textPromises) {
console.log(await textPromise);
}
}

异步遍历器(Async Iterator)

es2018引入,为异步操作提供原生的遍历器接口:异步返回value和done

特点:异步遍历器的next()方法返回一个Promise对象。

类似对象的同步遍历器部署Symbol.iterator属性,支持for...of,对象的异步遍历器部署Symbol.asynciterator属性,支持for await...of。

即,可遍历对象的Symbol.asynciterator属性返回一个异步Generator函数

const asyncIterator = asyncIterable[Symbol.asyncIterator]();  

注意,for await...of循环也可以用于同步遍历器。

异步遍历器重要的是:可以接近相同的方式处理同步操作和异步操作。

// 同步Generator函数
function* map(iterable, func) {
const iter = iterable[Symbol.iterator]();
while (true) {
const {value, done} = iter.next();
if (done) break;
yield func(value);
}
} // 异步Generator函数
async function* map(iterable, func) {
const iter = iterable[Symbol.asyncIterator]();
while (true) {
const {value, done} = await iter.next();
if (done) break;
yield func(value);
}
}

异步Generator函数

async函数与Generator函数的结合

  • await:用于将外部操作产生的值输入函数内部
  • yield:用于将函数内部的值输出

Generator函数返回同步遍历器对象,异步Generator函数返回异步遍历器对象。

JS - ECMAScript2015(ES6)新特性的更多相关文章

  1. Atitit js es5 es6新特性 attilax总结

    Atitit js es5 es6新特性 attilax总结 1.1. JavaScript发展时间轴:1 1.2. 以下是ES6排名前十的最佳特性列表(排名不分先后):1 1.3. Es6 支持情况 ...

  2. Atitit js版本es5 es6新特性

    Atitit js版本es5 es6新特性 Es5( es5 其实就是adobe action script的标准化)1 es6新特性1 Es5( es5 其实就是adobe action scrip ...

  3. 必须掌握的ES6新特性

    ES6(ECMAScript2015)的出现,让前端开发者收到一份惊喜,它简洁的新语法.强大的新特性,带给我们更便捷和顺畅的编码体验,赞! 以下是ES6排名前十的最佳特性列表(排名不分先后): 1.D ...

  4. ES6新特性概览

    本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony( ...

  5. 轻松学会ES6新特性之生成器

    生成器虽然是ES6最具魔性的新特性,但也是最难懂得的一节,笔者写了大量的实例来具体化这种抽象的概念,能够让人一看就懂,目的是希望别人不要重复或者减少笔者学习生成器的痛苦经历. 在说具体的ES6生成器之 ...

  6. 你不知道的JavaScript--Item24 ES6新特性概览

    ES6新特性概览 本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代 ...

  7. 前端入门21-JavaScript的ES6新特性

    声明 本篇内容全部摘自阮一峰的:ECMAScript 6 入门 阮一峰的这本书,我个人觉得写得挺好的,不管是描述方面,还是例子,都讲得挺通俗易懂,每个新特性基本都还会跟 ES5 旧标准做比较,说明为什 ...

  8. 34.js----JS 开发者必须知道的十个 ES6 新特性

    JS 开发者必须知道的十个 ES6 新特性 这是为忙碌的开发者准备的ES6中最棒的十个特性(无特定顺序): 默认参数 模版表达式 多行字符串 拆包表达式 改进的对象表达式 箭头函数 =&> ...

  9. ES6新特性概览1

    本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony( ...

  10. 【微信小程序+ES6新特性应用】字符串模板:美元符号$+大括号{}变量的写法

    1.字符串模板简介 ES6新特性中的字符串模板允许使用英文字符抑音符号`(提示:这里我们不能将其理解为单引号)来创建字符串,并且在该字符串中可以包含都[美元符号+大括号]包裹的变量 格式:consol ...

随机推荐

  1. event对象的理解

    0.给对象绑定事件准确的说是给对象事件绑定事件函数 1.event:事件对象,当一个事件发生的时候,和当前这个对象发生的事件有关的信息都会被i临时保存到event对象中 2.event对象必须在一个事 ...

  2. Netty学习第三节Netty的入门级学习

    1.原生NIO存在哪些缺陷     (1)NIO的类库和API繁杂,使用也比较麻烦,需要熟练掌握selector.ServerSocketChannel.SocketChannel.ByteBuffe ...

  3. java使用WebUploader做大文件的分块和断点续传

    版权所有 2009-2018荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/in ...

  4. (转)Entity Framework Extended Library (EF扩展类库,支持批量更新、删除、合并多个查询等)

    转自:http://www.cnblogs.com/jinzhao/archive/2013/05/31/3108755.html 今天乍一看,园子里居然没有关于这个类库的文章,实在是意外毕竟已经有很 ...

  5. 休息,考完了MCSD

    终于考完了~这次的证书签名居然还是鲍尔默的.

  6. gulp布局构建小结

    一.工具选择CSS预处理语言LESS 构建工具gulp(基于node环境)gulp插件:gulp-connect——主要是用来运行一个webserver npm install --save-dev ...

  7. OpenGL ES 光照模型之——环境光照(RenderMonkey测试)

    概述及目录(版权所有,请勿转载 www.cnblogs.com/feng-sc/) 本文总结如何在RenderMonkey下做简单的OpenGL ES环境光光照模型测试. 主要包括如下内容: 1.使用 ...

  8. laravel命令

    新建控制器 php artisan make:controller IssuesController 新建控制器并自动生成对应RESTful风格路由相关CURD方法 php artisan make: ...

  9. 理解Struts2的Action中的setter方法是怎么工作的

    接触过webwork和Struts2的同行都应该知道, 提交表单的时候,只要Action中的属性有setter 方法,这些表单数据就可以正确赋值到Action中属性里:另外对于Spring配置文件中声 ...

  10. Ajax请求php返回json对象数据中包含有数字索引和字符串索引,在for in循环中取出数据的顺序问题

    //php中的数组数据格式 Array ( [all] => Array ( [title] => ALL [room_promotion_id] => all ) [best_av ...