JavaScript大杂烩13 - 总结ECMAScript 5新功能
var Dog = {
name : 'dog',
speak : function () { alert('Woof!'); }
};
var dog = Object.create(Dog);
dog.speak();
这里就是使用了这个方法创建了Dog的一个实例dog,这种方式的本质其实还是与我们之前讨论的使用空对象挂接原型对象是一样的,代码基本就像这样:
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
使用这种方式较之使用构造函数加new的方式来说更加简洁,但是不能设置私有和公开成员,而且实例成员在各个实例之间不共享,所以也有一定的局限性。
Object.create(prototype, descriptors)
参数
prototype:必需。 要用作原型的对象。 可以为 null,一般也可以在需要的时候使用getPrototypeOf方法获取。
descriptors: 可选。 定义的一组属性的对象字面量,该对象包含了每个属性的描述对象。
属性描述对象称为属性的attributes对象,其含有如下成员:
value:表示该属性的值,默认为undefined。
writable:表示该属性的值(value)是否可以改变,默认为true。这个值如果是false的话,即使是继承的子类的话,也无法修改属性的值,这个也是讲得通的。
enumerable: 表示该属性是否可枚举,默认为true,也就是该属性会出现在for...in和Object.keys()等操作中。
configurable:表示“可配置性”,默认为true。如果设为false,表示无法删除该属性,也不得改变attributes对象(value属性除外),也就是configurable属性控制了attributes对象本身的可写性。
get:表示该属性的取值函数(getter),默认为undefined。
set:表示该属性的存值函数(setter),默认为undefined。
返回值
一个具有指定的内部原型且包含指定的属性(如果有)的新对象。
毫无疑问,这个函数最有意义的应该就是第二个参数:一组属性描述对象,这个在别的语言中非常有用的特性姗姗来迟,虽然在JavaScript中可以直接使用dog.age=2这种方式定义和修改属性,但是这种数据成员终究不满足封装性的需求,而且不满足属性本质上是函数这种惯例,在这个版本中满足封装性的属性(本质上是函数)终于出现在大家视野中了,我们看一个例子来了解一下如何定义一组属性:
var Shape = { twoDimensional: true, color: 'Red'};
var Square = Object.create(Shape, {
// 简单的属性,不包含任何的其他逻辑的属性
type: { value: 'square', enumerable: true, writable: true },
// 复杂一点的属性,包含有一些逻辑的属性
size: {
get: function() { return this.__size__;},
set: function(pSize) {
if (pSize > 10) alert('Too large...');
// 其他的处理逻辑,例如简单的保存一下
this.__size__ = pSize;
},
enumerable: true
}
});
var square = Object.create(Square);
square.type = 'rectangle';
alert(square.type);
square.size = 9;
alert(square.size);
使用起来还是很简单的,但是有一点不太优雅的代码就是this.__size__这个保存属性值的成员,为了满足封装性,我们得使用一下闭包的特性了:
var Square = Object.create(Shape, (function () {
var m_size; return {
// 简单的属性,不包含任何的其他逻辑的属性
type: { value: 'square', enumerable: true, writable: true },
// 复杂一点的属性,包含有一些逻辑的属性
size: {
get: function() { return m_size;},
set: function(pSize) {
// 常见的条件检查
if (pSize > 10) alert('Too large...');
// 其他的处理逻辑,例如简单的保存一下
m_size = pSize;
},
enumerable: true
}
};
}()));
把Square定义的那段代码换成上面这段,就有点样子了。
var Shape = { twoDimensional: true, color: 'Red'};
var square = Object.create(Shape);
Object.defineProperty(square, 'type', {
value : 'square',
enumerable : true,
writable: true
});
square.type = 'rectangle';
alert(square.type);
使用defineProperties方法就与create中的第二个参数一致了,参见:
var Shape = { twoDimensional: true, color: 'Red'};
var square = Object.create(Shape);
Object.defineProperties(square, (function () {
var m_size; return {
// 简单的属性,不包含任何的其他逻辑的属性
type: { value: 'square', enumerable: true, writable: true },
// 复杂一点的属性,包含有一些逻辑的属性
size: {
get: function() { return m_size;},
set: function(pSize) {
// 常见的条件检查
if (pSize > 10) alert('Too large...');
// 其他的处理逻辑,例如简单的保存一下
m_size = pSize;
},
enumerable: true
}
};
}()));
square.type = 'rectangle';
alert(square.type);
square.size = 9;
alert(square.size);
注意defineProperty/defineProperties这两个函数的返回值就是修改后的对象,有时候会使用这个返回值。
var Shape = {
get type() { return this.__type__;},
set type(value) { this.__type__ = value;}
};
var square = Object.create(Shape);
square.type = 'rectangle';
alert(square.type);
简单吧,很简洁,非常强大。
var o = { name: 'frank'};
Object.defineProperties(o, {
p1: { value: 1, enumerable: true },
p2: { value: 2, enumerable: false }
});
alert(Object.keys(o));
alert(Object.getOwnPropertyNames(o));
注意name这种原始的属性是可枚举的,以前通过for/in结合hasOwnProperty方法才能完成枚举对象自身定义的属性的功能现在直接可以通过遍历keys完成了。
preventExtensions方法禁止对象添加新属性,isExtensible检测对象是否使用了preventExtensions方法。
seal方法禁止对象添加新属性和禁止删除已有属性,isSealed检测对象是否使用了seal方法。
freeze方法禁止对对象做任何修改,不能添加新属性和删除已有属性,也不能修改对象的属性值,isFrozen检测对象是否使用了freeze方法。
看到了吧,一个比一个严格,等到了使用freeze方法的时候,对象完全变成了只读对象,这个在很多场合下还是很有用的。看个简单的例子:
var o = { name: 'frank'};
Object.preventExtensions(o);
o.age = 10;
alert(o.age); //undefined,代表无法添加新属性
Object.seal(o);
delete o.name;
alert(o.name); // 删除不了
Object.freeze(o);
o.name = 'dong';
alert(o.name); // 无法修改
var a = ['a','b','c','b'];
alert(a.indexOf('b')); //
alert(a.indexOf('y')); // -1
alert(a.lastIndexOf('b')); //
2. every/some/forEach/filter/map/reduce/reduceRight
[1, 2, 3].map(function(item, index, arr){
return item * item;
});
// [1, 4, 9]
通过函数的call方法,map方法可以用于字符串。
[].map.call('abc', function (x) { return x.toUpperCase() })
// [ 'A', 'B', 'C' ]
// 或者
'abc'.split('').map(function (x) { return x.toUpperCase() })
// [ 'A', 'B', 'C' ]
forEach方法对所有元素依次执行一个函数,它与map的区别在于不返回新数组,而是对原数组的成员执行某种操作,甚至可能改变原数组的值。
[1, 2, 3].forEach(function(item, index, arr){
console.log("array[" + index + "] = " + item);
});
// array[0] = 1
// array[1] = 2
// array[2] = 3
从上面代码可以看到,map和forEach的参数格式是一样的,都是一个函数。该函数接受三个参数,分别是当前元素、当前元素的位置(从0开始)、整个数组。
var out = [];
[1, 2, 3].map(function(item, index, arr){
this.push(item * item);
}, out);
out // [1, 4, 9]
上面代码表示,如果提供一个数组作为第二个参数,则函数内部的this关键字就指向这个数组。
[1,2,3,4,5].filter(function(item){
return (item>3);
})
// [4,5]
上面代码将大于3的原数组成员,作为一个新数组返回。
[1, 2, 3, 4, 5].filter(function(item, index, arr){
return index % 2 === 0;
});
// [1, 3, 5]
上面代码返回原数组偶数位置的成员组成的新数组。
[1, 2, 3, 4, 5].some(function(item, index, arr){
return item >= 3;
});
// 返回true
上面代码表示,如果存在大于等于3的数组成员,就返回true。
[1, 2, 3, 4, 5].every(function(item, index, arr){
return item >= 3;
});
// 返回false
上面代码表示,只有所有数组成员大于等于3,才返回true。
用来累计的变量(即当前状态)
数组的当前元素
当前元素在数组中的序号(从0开始)
原数组
这四个参数之中,只有前两个是必须的,后两个则是可选的。
[1, 2, 3, 4, 5].reduce(function(x, y){
return x+y;
});
//
上面代码的参数x表示累计变量,默认为0,y则是数组的当前元素。reduce方法依次将每个数组元素加入x,最终返回它们的总和15。
Array.prototype.sum = function (){
return this.reduce(function (partial, value){
return partial + value;
})
};
[3,4,5,6,10].sum()
//
如果要对累计变量指定初值,可以把它放在reduce方法的第二个参数。
[1, 2, 3, 4, 5].reduce(function(x, y){
return x+y;
}, 10);
//
上面代码指定参数x的初值为10,所以数组元素从10开始累加,最终结果为25。
function findLongest(entries) {
return entries.reduce(function (longest, entry) {
return entry.length > longest.length ? entry : longest;
}, '');
}
var names = ['Collis', 'Cyan'];
Array.isArray(names); // true
// 仅仅绑定了this,还需要主动的通过对象去调用
tooltip.show = showText.bind(tooltip);
tooltip.show();
overlay.show = showText.bind(overlay);
overlay.show();
// 直接调用的apply/call形式
showText.call(tooltip);
showText.call(overlay);
Date.now()
// 1364026285194类似的数字
如果需要更精确的时间,可以使用window.performance.now()。它提供页面加载到命令运行时的已经过去的时间,单位是浮点数形式的毫秒。
window.performance.now()
// 21311140.415类似的数字
这一组方法可用于生成一种唯一的id标识。
alert(new Date().toJSON());
" hello world ".trim()
// "hello world"
JavaScript大杂烩13 - 总结ECMAScript 5新功能的更多相关文章
- ECMAScript es6新功能讲解视频教程
下载链接:https://www.yinxiangit.com/1.html 目录: 01.课程介绍-ECMAScript 新功能.mp402.块的作用域-let.mp403.恒量-const.mp4 ...
- Python Twisted系列教程13:使用Deferred新功能实现新客户端
作者:dave@http://krondo.com/deferred-all-the-way-down/ 译者:杨晓伟(采用意译) 你可以从这里从头阅读这个系列. 介绍 回忆下第10部分中的客户端5 ...
- ECMAScript 2016,2017 和 2018 中所有新功能的示例
很难追踪 JavaScript(ECMAScript)中的新功能. 想找到有用的代码示例更加困难. 因此,在本文中,我将介绍 TC39 已完成 ES2016,ES2017 和 ES2018(最终草案) ...
- [转]ECMAScript 2016,2017 和 2018 中所有新功能的示例
很难追踪 JavaScript(ECMAScript)中的新功能. 想找到有用的代码示例更加困难. 因此,在本文中,我将介绍 TC39 已完成 ES2016,ES2017 和 ES2018(最终草案) ...
- 探秘IntelliJ IDEA 13测试版新功能——调试器显示本地变量
IntelliJ IDEA在业界被公认为最好的Java开发平台之一,JetBrains公司将在12月正式发布IntelliJ IDEA 13版本. 现在,小编将和大家一起探秘密IntelliJ IDE ...
- Cobalt Strike 3.13的新功能
Cobalt Strike 3.13现已推出.此版本添加了TCP Beacong,进程参数欺骗,并将Obfuscate和Sleep功能扩展到SMB和TCP Beacons. TCP Beacon Co ...
- Java 17 将要发布,补一下 Java 13 中的新功能
本文章属于Java 新特性教程 系列,已经收录在 Github.com/niumoo/JavaNotes ,点个赞,不迷路. 自从 Oracle 调整了 Java 的版本发布节奏之后,Java 版本发 ...
- 超详细 Java 15 新功能介绍
点赞再看,动力无限.微信搜「程序猿阿朗 」,认认真真写文章. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. Java 15 在 2 ...
- Visual Studio 2017十五项新功能体验
Visual Studio 2017正式已经于2017.3.7号正式发布,选在这一天发布也是为了纪念Visual Studio 二十周年.MVP 2017技术峰会将于这个周末(3.17)在北京举办,由 ...
随机推荐
- Unicode 字符串排序规则(一):如何确定单个字符的顺序
一.一个具体的例子引发的问题 当今是国际化的时代,多种语言可能同时显示在屏幕上.比如一个人可能喜欢听华语歌.英文歌.韩文歌和日语歌,又比如他的联系人中有中国人.英国人.日本人.韩国人以及有英文名字的中 ...
- lable标签的用途
lable标签的用途:为iput输入框元素定义标注: label 元素不会向用户呈现任何特殊效果.不过,它为鼠标用户改进了可用性.如果您在 label 元素内点击文本,就会触发此控件.就是说,当用户选 ...
- A Nice Paper About Mobile Data Offloading
关于Mobile Data Offloading这个研究领域的Paper基本上该有的都看过了,我想即使再有也无非是那些套路,新不到哪去.同样,这篇paper也是这样,它的出发点是改进原有的利用ad h ...
- Http请求-get和post的区别
GET和POST是HTTP请求的两种基本方法. 最直观的区别就是GET把参数包含在URL中,以?的方式来进行拼接,POST通过request body传递参数.并且GET请求在URL中传送的参数是有长 ...
- 从svn下载项目,并在tomcat启动
1.需要先在本地安装mysql,并且启动成功(配置环境变量.客户端等). 2.需要下载小乌龟,需要从svn上下载项目. 3.安装eclipse,并且在eclipse上下载项目,会下载成两个聚合项目,不 ...
- ArrayList的实现原理
ArrayList的线性复杂度是1.想确定一个数据,直接通过索引进行访问.实际上这个过程和数组是非常相似的.ArrayList在整个使用过程中,如果想要高效操作,最好设置一个数组的大小.在个数固定的情 ...
- 解决Android Studio 3.x版本的安装时没有SDK,运行时出现SDK tools错误
好久没更新了,最近手机上的闹钟APP没一个好用的,所以想自己写个. 那Android开发环境搭起来,注意先装好jdk. 1.安装Android Studio google的Android开发网站已经有 ...
- Netty自带连接池的使用
一.类介绍1.ChannelPool——连接池接口 2.SimpleChannelPool——实现ChannelPool接口,简单的连接池实现 3.FixedChannelPool——继承Simple ...
- Makefile.am文件配置
Makefile.am Makefile.am是一种比Makefile更高层次的编译规则,可以和configure.in文件一起通过调用automake命令,生成Makefile.in文件,再调用./ ...
- SVM笔记
1.前言 SVM(Support Vector Machine)是一种寻求最大分类间隔的机器学习方法,广泛应用于各个领域,许多人把SVM当做首选方法,它也被称之为最优分类器,这是为什么呢?这篇文章将系 ...