前言:
写几个常用的es5的方法,以便查阅复习。
1.新增的object接口
对象 | 构造器 | 描述 |
---|---|---|
Object | getOwnPropertyName | 返回一个对象,包括对象所有自有属性名称集合(包括不可枚举的属性) |
Object | getPrototypeOf | 返回对象的原型 |
Object | create | 创建对象(创建一个拥有置顶原型和若干个指定属性的对象) |
Object | defineProperty | 给对象定义一个新属性,或者修改已有的属性,并返回 |
Object | definePropertys | 在一个对象上添加或修改一个或者多个自有属性,并返回该对象 |
Object | keys | 返回一个由给定对象的所有可枚举自身属性的属性名组成的数组 |
注意返回值
Object.create(proto, [propertiesObject])
参数说明:
proto:创建的新对象的原型对象
[propertiesObject]:可选,添加到新创建对象的可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()的第二个参数。
注意:
1.proto的取值如果不是null,或者一个对象就会报错
2.可实现继承请参考MDN
Object.defineProperty(obj, prop, descriptor)
参数说明:
obj:需要传入的对象
prop:需要定义的属性或者需要修改的属性
descriptor:属性值描述器,用于定义或修改该属性的特性,属性值的描述器有两种一种是数据描述符,一种是存取描述符(get-setter),这两种不可能同时存在。
descriptor的取值有六个
-
configurable(可以删除目标属性或是否可以再次修改属性的特性(writable, configurable, enumerable))
-
enumerable(此属性是否可以被枚举(使用for…in或Object.keys())。设置为true可以被枚举;设置为false,不能被枚举。默认为false。)
-
value(只有数据描述符有)
-
writeable(只有数据描述符有)(是否可重新赋值,true为可重新赋值,false为不可重新赋值)
-
get(只有存取描述符有)
-
set(只有存取描述符有)
特别注意以下几点:
1.这些选项不一定是自身属性,如果是继承来的也要考虑。为了确认保留这些默认值,你可能要在这之前冻结 Object.prototype,明确指定所有的选项,或者通过 Object.create(null)将proto属性指向null。
2.如果对象可枚举,则使用for…in或Object.keys()可以遍历
例子一:数据描述符
var obj = Object.create(null);
Object.defineProperty(obj, 'name', { value:'峰峰', writable:true })
obj.name = '小倩';
console.log(obj);//{"name":"小倩"}
Object.defineProperty(obj, 'name', { writable:false })
obj.name = '峰峰'; //虽然writeable的值是false,但是仍然不会报错
console.log(obj);//{"name":"小倩"}
例子二:存取描述符
var obj = Object.create(null);
var initVal = '峰峰';
Object.defineProperty(obj, 'name', { get:function(){ return initVal; }, set:function(setVal){//参数为设置的值 initVal = setVal; } })
console.log(obj.name);//'峰峰'
console.log(obj);// { }此时是空的obj
obj.name = '小倩';
console.log(obj);// { }此时是空的obj
例子三:configurable可修改属性特性或者删除目标属性
var obj = Object.create(null);
Object.defineProperty(obj, 'name', { value:'峰峰', configurable:true })
console.log(obj.name);//'峰峰'
delete obj.name;
console.log(obj.name);//undefined
--------------------------------------------------------------------------
var obj = Object.create(null);
Object.defineProperty(obj, 'name', { value:'峰峰', configurable:false })
console.log(obj.name);//'峰峰'
delete obj.name; //不会报错
console.log(obj.name);//'峰峰'
var obj = {}
//第一种情况:configurable设置为false,不能再次修改特性。、
Object.defineProperty(obj,"name",{ value:"峰峰", writable:false, enumerable:false, configurable:false });
//重新修改特性
Object.defineProperty(obj,"name",{ value:"峰峰", writable:true, enumerable:true, configurable:true });
console.log( obj.name); //报错:Uncaught TypeError: Cannot redefine property: name
//第二种情况:configurable设置为true,可以再次修改特性。
Object.defineProperty(obj,"name",{ value:"峰峰", writable:false, enumerable:false, configurable:true });
//重新修改特性
Object.defineProperty(obj,"name",{ value:"峰峰", writable:true, enumerable:true, configurable:true });
console.log( obj.name); //峰峰
例子四:enumerable(是否可枚举)
var obj = {}
//第一种情况:enumerable设置为false,不能被枚举。
Object.defineProperty(obj,"name",{ value:"峰峰", writable:false, enumerable:false });
//枚举对象的属性
for( var attr in obj ){ console.log( attr ); } //空的
//第二种情况:enumerable设置为true,可以被枚举。
Object.defineProperty(obj,"name",{ value:"峰峰", writable:false, enumerable:true });
//枚举对象的属性
for( var attr in obj ){ console.log( attr ); //name}
注意:enumerable写错了不会报错!
Object.defineProperties(obj, {prop1:descriptor1,prop2:descriptor2})
此方法和 Object.defineProperty类似,只不过是可以定义多个属性,或者修改多个属性的特性。用法如下例子
var obj = {};
Object.defineProperties(obj, {
'property1': { value: true, writable: true },
'property2': { value: 'Hello', writable: false }
});
Object.keys(obj)
参数说明:
obj:要获取属性的对象
返回一个数组
方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for…in 循环遍历该对象时返回的顺序一致 。
// simple array
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']
// array like object
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']
// array like object with random key ordering
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // console: ['2', '7', '100']
// getFoo is a property which isn't enumerable
var myObj = Object.create({}, {
getFoo: {
value: function () { return this.foo; }
}
});
myObj.foo = 1;
console.log(Object.keys(myObj)); // console: ['foo']
Object.getOwnPropertyName (obj)
参数说明:
obj:要获取属性的对象
返回一个数组
Object.keys()只能获取其可枚举的自身属性,Object.getOwnPropertyName就用来获取所有的自身属性,包括不可枚举的
var arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]
// 类数组对象
var obj = { 0: "a", 1: "b", 2: "c"};
console.log(Object.getOwnPropertyNames(obj).sort()); // ["0", "1", "2"]
// 使用Array.forEach输出属性名和属性值
Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) {
console.log(val + " -> " + obj[val]);
});
// 输出
// 0 -> a
// 1 -> b
// 2 -> c
//不可枚举属性
var my_obj = Object.create({}, {
getFoo: {
value: function() { return this.foo; },
enumerable: false
}
});
my_obj.foo = 1;
console.log(Object.getOwnPropertyNames(my_obj).sort()); // ["foo", "getFoo"]
2.新增的Array接口
对象 | 构造器 | 说明 |
---|---|---|
Array | indexOf | 返回根据给定元素找到的第一个索引值,否则返回-1 |
Array | lastIndexOf | 方法返回指定元素在数组中的最后一个的索引,如果不存在则返回 -1 |
Array | every | 测试数组的所有元素是否都通过了指定函数的测试 |
Array | some | 测试数组中的某些元素是否通过了指定函数的测试 |
Array | map | 返回一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组 |
Array | forEach | 让数组的每一项都执行一次给定的函数 |
Array | filter | 利用所有通过指定函数测试的元素创建一个新的数组,并返回 |
Array | reduce | 接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终为一个值 |
Array | recuceRifht | 接受一个函数作为累加器,让每个值(从右到左,亦即从尾到头)缩减为一个值 |
注意返回值
arr.every(callback[, thisArg])
参数说明:
callback:回调函数,用来测试每个元素。
[, thisArg],可选,执行 callback 时使用的 this 值。如果不填则this是window.
返回值:true,false
every 方法为数组中的每个元素执行一次 callback 函数,直到它找到一个使 callback 返回 false(表示可转换为布尔值 false 的值)的元素。如果发现了一个这样的元素,every 方法将会立即返回 false。否则,callback 为每一个元素返回 true,every 就会返回 true。callback 只会为那些已经被赋值的索引调用。不会为那些被删除或从来没被赋值的索引调用。
callback 被调用时传入三个参数:元素值,元素的索引,原数组。
如果为 every 提供一个 thisArg 参数,则该参数为调用 callback 时的 this 值。如果省略该参数,则 callback 被调用时的 this 值,在非严格模式下为全局对象,在严格模式下传入 undefined。
every 不会改变原数组。
every 遍历的元素范围在第一次调用 callback 之前就已确定了。在调用 every 之后添加到数组中的元素不会被 callback 访问到。如果数组中存在的元素被更改,则他们传入 callback 的值是 every 访问到他们那一刻的值。那些被删除的元素或从来未被赋值的元素将不会被访问到。
every 和数学中的"所有"类似,当所有的元素都符合条件才返回true。另外,空数组也是返回true。(空数组中所有元素都符合给定的条件,注:因为空数组没有元素)。
arr.some(callback[, thisArg])
arr.some与arr.every几乎相同只不过,some是某些,只要有满足callback的就会返回true,类似数学中的‘任何’。
var newArray= arr.map(function callback(currentValue[, index[, array]]) { }[, thisArg])
参数说明:
callback:一个用来创建新数组的函数,需要传入三个参数,1.当前原始数组的值,2.当前索引,3.原始数组
thisArg:callback函数中的this,若不填则是this指向window
返回值:
一个新数组。满足callback函数
map 方法会给原数组中的每个元素都按顺序调用一次 callback 函数。callback 每次执行后的返回值(包括 undefined)组合起来形成一个新数组。 callback 函数只会在有值的索引上被调用;那些从来没被赋过值或者使用 delete 删除的索引则不会被调用。
callback 函数会被自动传入三个参数:数组元素,元素索引,原数组本身
如果 thisArg 参数有值,则每次 callback 函数被调用的时候,this 都会指向 thisArg 参数上的这个对象。如果省略了 thisArg 参数,或者赋值为 null 或 undefined,则 this 指向全局对象 。
map 不修改调用它的原数组本身(当然可以在 callback 执行时改变原数组)。
使用 map 方法处理数组时,数组元素的范围是在 callback 方法第一次调用之前就已经确定了。在 map 方法执行的过程中:原数组中新增加的元素将不会被 callback 访问到;若已经存在的元素被改变或删除了,则它们的传递到 callback 的值是 map 方法遍历到它们的那一时刻的值;而被删除的元素将不会被访问到。
下面的例子演示如何在一个 String 上使用 map 方法获取字符串中每个字符所对应的 ASCII 码组成的数组:
var map = Array.prototype.map
var a = map.call("Hello World", function(x) {
return x.charCodeAt(0);
})
// a的值为[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
arr.forEach(function callback(currentValue[, index[, array]]) { }[, thisArg])
参数说明:
同arr.map
返回值:
undefined;
forEach 方法按升序为数组中含有效值的每一项执行一次callback 函数,那些已删除或者未初始化的项将被跳过(例如在稀疏数组上)。
forEach() 为每个数组元素执行callback函数;不像map() 或者reduce() , forEach()总是返回 undefined值,并且不可链式调用。
例子:for转换成forEach
//转换之前
const items = ['item1', 'item2', 'item3'];
const copy = [];
for (let i=0; i<items.length; i++) {
copy.push(items[i])
}
转换之后
const items = ['item1', 'item2', 'item3'];
const copy = [];
items.forEach(function(item){
copy.push(item)
});
function logArrayElements(element, index, array) {
console.log("a[" + index + "] = " + element);
}
// 注意索引2被跳过了,因为在数组的这个位置没有项
[2, 5, ,9].forEach(logArrayElements);
// a[0] = 2
// a[1] = 5
// a[3] = 9
[2, 5,"" ,9].forEach(logArrayElements);
// a[0] = 2
// a[1] = 5
// a[2] =
// a[3] = 9
[2, 5, undefined ,9].forEach(logArrayElements);
// a[0] = 2
// a[1] = 5
// a[2] = undefined
// a[3] = 9
let xxx;
// undefined
[2, 5, xxx ,9].forEach(logArrayElements);
// a[0] = 2
// a[1] = 5
// a[2] = undefined
// a[3] = 9
function Counter() {
this.sum = 0;
this.count = 0;
}
Counter.prototype.add = function(array) {
array.forEach(function(entry) {
this.sum += entry;
++this.count;
}, this);
//console.log(this);this是Counter构造函数
};
var obj = new Counter();
obj.add([1, 3, 5, 7]);
obj.count;
// 4 === (1+1+1+1)
obj.sum;
// 16 === (1+3+5+7)
一个很好的应用(对象复制函数)
function copy(obj) {
var copy = Object.create(Object.getPrototypeOf(obj));
var propNames = Object.getOwnPropertyNames(obj);
propNames.forEach(function(name) {
var desc = Object.getOwnPropertyDescriptor(obj, name);
Object.defineProperty(copy, name, desc);
});
return copy;
}
var obj1 = { a: 1, b: 2 };
var obj2 = copy(obj1); // obj2 looks like obj1 now
如果数组在迭代时被修改了,则其他元素会被跳过。
var words = ["one", "two", "three", "four"];
words.forEach(function(word) {
console.log(word);
if (word === "two") {
words.shift();
}
});
// one
// two
// four
var new_array = arr.filter(function callback(currentValue[, index[, array]]) { }[, thisArg])
参数说明:
同forEach()
filter 为数组中的每个元素调用一次 callback 函数,并利用所有使得 callback 返回 true 或 等价于 true 的值 的元素创建一个新数组。callback 只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。那些没有通过 callback 测试的元素会被跳过,不会被包含在新数组中。
callback 被调用时传入三个参数:
元素的值
元素的索引
被遍历的数组
如果为 filter 提供一个 thisArg 参数,则它会被作为 callback 被调用时的 this 值。否则,callback 的 this 值在非严格模式下将是全局对象,严格模式下为 undefined。
callback 最终观察到的this值是根据通常函数所看到的 "this"的规则确定的。
filter 不会改变原数组,它返回过滤后的新数组。
filter 遍历的元素范围在第一次调用 callback 之前就已经确定了。在调用 filter 之后被添加到数组中的元素不会被 filter 遍历到。如果已经存在的元素被改变了,则他们传入 callback 的值是 filter 遍历到它们那一刻的值。被删除或从来未被赋值的元素不会被遍历到。
arr.reduce(function callback(accumulator,currentValue[, index[, array]]) { }[, initialValue])
参数说明:
callback里面的四个参数,accumulator:累加器;currentValue:当前值;index:索引;array:原始数组;
initialValue:作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。;
accumulator: 累计器累计回调的返回值; 它是上一次调用回调时返回的累积值 ,或者initialValue。
注意:
回调函数第一次执行时,accumulator 和currentValue的取值有两种情况:如果调用reduce()时提供了initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值;如果没有提供 initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值。
用途:
用来求数组的和:
var sum = [0, 1, 2, 3].reduce(function (a, b) {
return a + b;
}, 0);
// sum is 6
将二维数组化为一维的:
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
function(a, b) {
return a.concat(b);
},
[]
);
// flattened is [0, 1, 2, 3, 4, 5]
计算数组中每个元素出现的次数:
var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var countedNames = names.reduce(function (allNames, name) {
if (name in allNames) {
allNames[name]++;
}
else {
allNames[name] = 1;
}
return allNames;
}, {});
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
数组去重
let arr = [1,2,1,2,3,5,4,5,3,4,4,4,4];
let result = arr.sort().reduce((init, current)=>{
if(init.length===0 || init[init.length-1]!==current){
init.push(current);
}
return init;
}, []);
console.log(result); //[1,2,3,4,5]