JS - ECMAScript2015(ES6)新特性
友情提示:本文仅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()
: 忽略enumerable
为false
的属性,只拷贝对象自身的可枚举的属性
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
)的基础上,新增Map
和Set
- 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的显式绑定(call
、apply
、bind
)。
::双冒号运算符(函数绑定运算符),可以用来取代call
、apply
、bind
调用。
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支持异步操作,即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)新特性的更多相关文章
- Atitit js es5 es6新特性 attilax总结
Atitit js es5 es6新特性 attilax总结 1.1. JavaScript发展时间轴:1 1.2. 以下是ES6排名前十的最佳特性列表(排名不分先后):1 1.3. Es6 支持情况 ...
- Atitit js版本es5 es6新特性
Atitit js版本es5 es6新特性 Es5( es5 其实就是adobe action script的标准化)1 es6新特性1 Es5( es5 其实就是adobe action scrip ...
- 必须掌握的ES6新特性
ES6(ECMAScript2015)的出现,让前端开发者收到一份惊喜,它简洁的新语法.强大的新特性,带给我们更便捷和顺畅的编码体验,赞! 以下是ES6排名前十的最佳特性列表(排名不分先后): 1.D ...
- ES6新特性概览
本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony( ...
- 轻松学会ES6新特性之生成器
生成器虽然是ES6最具魔性的新特性,但也是最难懂得的一节,笔者写了大量的实例来具体化这种抽象的概念,能够让人一看就懂,目的是希望别人不要重复或者减少笔者学习生成器的痛苦经历. 在说具体的ES6生成器之 ...
- 你不知道的JavaScript--Item24 ES6新特性概览
ES6新特性概览 本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代 ...
- 前端入门21-JavaScript的ES6新特性
声明 本篇内容全部摘自阮一峰的:ECMAScript 6 入门 阮一峰的这本书,我个人觉得写得挺好的,不管是描述方面,还是例子,都讲得挺通俗易懂,每个新特性基本都还会跟 ES5 旧标准做比较,说明为什 ...
- 34.js----JS 开发者必须知道的十个 ES6 新特性
JS 开发者必须知道的十个 ES6 新特性 这是为忙碌的开发者准备的ES6中最棒的十个特性(无特定顺序): 默认参数 模版表达式 多行字符串 拆包表达式 改进的对象表达式 箭头函数 =&> ...
- ES6新特性概览1
本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony( ...
- 【微信小程序+ES6新特性应用】字符串模板:美元符号$+大括号{}变量的写法
1.字符串模板简介 ES6新特性中的字符串模板允许使用英文字符抑音符号`(提示:这里我们不能将其理解为单引号)来创建字符串,并且在该字符串中可以包含都[美元符号+大括号]包裹的变量 格式:consol ...
随机推荐
- 在cygwin中执行bat文件
在cygwin中执行bat文件 #!/bin/bash dir_gen_image_bat=C:/MinGW/msys/1.0/home/Administrator/feitian_audio/FOT ...
- cuda使用
import torchx = torch.randn(2, 3)x = x.cuda() print (x)#最简单的cuda使用,但是感觉好慢啊
- 复制文件描述符---dup
函数功能:复制文件描述符 头文件:#include<unistd.h> 函数原型:int dup(int oldfd) 参数说明:oldfd:旧的文件描述符 返回值:成功返回-个新的文件描 ...
- KBMMW 4.81.00 发布
这次更新的速度非常快. 4.81.00 May 9 2015 Important notes (changes that may break existing code) ============== ...
- js级联出生日期
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- iOS的block内存管理
初始情况下: block本身.__block修饰的变量以及在block内部使用的变量都是在栈里的. __block修饰的变量的地址会作为实参传入block块内部(暂时先这么理解,实际比较复杂).blo ...
- Nvidia显卡驱动下载
https://www.nvidia.cn/Download/index.aspx?lang=cn https://blog.csdn.net/weixin_39643690/article/deta ...
- 点云库PCL学习
1. 点云的提取 点云的获取:RGBD获取 点云的获取:图像匹配获取(通过摄影测量提取点云数据) 点云的获取:三维激光扫描仪 2. PCL简介 PCL是Point Cloud Library的简称,是 ...
- (并查集)小希的迷宫 --HDU -- 1272
链接: http://acm.hdu.edu.cn/showproblem.php?pid=1272 http://acm.hust.edu.cn/vjudge/contest/view.action ...
- POJ 2462 / HDU 1154 Cutting a Polygon
就这样莫名其妙的过了,不过可以确定之前都是被精度卡死了.真心受不了精度问题了. 题意:一条直线在一个不规则多边形内的长度,包括边重合部分. 首先计算出所有交点,然后按想x,y的大小进行二级排序. 然后 ...