es5

es5复习

"准备es6"

绯雨闲丸 发布于

“”

ES5新增的内容

近期在开发React & React Native项目时, 经常有用到es6, 准备整理一下常用的es6内容, 在这之前先整理并复习一下es5的内容.

es5 各浏览器兼容性请参考http://kangax.github.io/compat-table/es5/

es5新增的内容并不多, 主要有:

严格模式

(注:在es6中并不需要使用严格模式)

可以在文件首行, 或函数体内首行加入’use strict’来把整个作用域变成严格模式

在严格模式下,会有如下一些限制:

  • 禁止使用 with 语句
  • 重名的属性会报错,重名的函数参数会报错
  • 未声明的变量赋值直接报错,而不是变成全局变量
  • 函数默认的 this 将变成 undefined 而不是默认指向 window
  • 对只读属性进行写操作,删除不可删除属性,对不可拓展的对象添加属性均会抛出异常

JSON API支持

原生支持JSON.parse与JSON.stringify

对象 API扩展

定义getter setter:

var obj = {};
Object.defineProperty(obj, "name", {
  get: function() {
    return name.toUpperCase();
    },
  set: function(n) {
    name=n;
    }
})

定义一个对象的属性是否可以修改、是否可以删除、是否可以配置, 是否可以添加

Object.defineProperty( obj, "value", {
    value: true,
    writable: false,
    enumerable: true,
    configurable: true,
    extensible: true,
});

冻结一个对象,冻结分两种:

  • Object.seal(obj), 使对象的属性配置无法修改, 属性不能添加,等价于给每一个属性都设置成 configurale=false
  • Object.freeze(obj),除了 seal 之外,它还会是属性值本身无法被修改,相当于对每个属性同时进行了 configurable=false 和 writable=false

调用对象父类原型上的方法: Object.getPrototypeOf(object):

function Person(){
    this.method1 = function(){alert(1)}
}
Person.prototype.method2 = function(){alert(2);}

function Man(){
    this.m1 = function(){
        Object.getPrototypeOf(this).method1();
    }
}
Man.prototype = new Person();

Man.prototype.m2 = function(){
    Object.getPrototypeOf(this).method2();
}


var man = new Man();
man.m1();
man.m2();

获取对象中属性的ECMAScript对象: Object.getOwnPropertyDescriptor(object, propertyname)

var obj = {};

obj.a = "abc";

var descriptor = Object.getOwnPropertyDescriptor(obj, "a");

for(var prop in descriptor){
    document.write(prop + ': ' + descriptor[prop]);
    document.write("<br />");
}

/*
configurable: true
enumerable: true
value: abc
writable: true
*/

用 ECMAScript对象 设置为object中多个属性的值: object.defineProperties(object, descriptors):

var obj = {};

obj.a = "abc";

Object.defineProperties(obj,{
    a:{
        configurable: true,
        enumerable: true,
        value: 'aaa',
        writable: false
    }
});
var descriptor = Object.getOwnPropertyDescriptor(obj, "a");
for(var prop in descriptor){
    document.write(prop + ': ' + descriptor[prop]);
    document.write("<br />");
}
/*
configurable: true
enumerable: true
value: aaa
writable: false
*/

避免加新属性加入对象(Extensible设置为false): Object.preventExtensions(object):

var obj = { a: "1"};

Object.preventExtensions(obj);
document.write(Object.isExtensible(obj));//false

obj.newProp = 50;
document.write(obj.newProp);//undefined

建立一个原型为prototype,descriptors为ECMAScript对象的对象: Object.create(prototype, descriptors):

var a = Object.create({a:1,b:2}, {
            c: {
                value: "large",
                enumerable: true
            },
            d: {
                value: "round",
                enumerable: true
            }
        });

判断对象是否为锁定,冻结,不可扩展的:

Object.isSealed(object);

Object.isFrozen(object);

Object.isExtensible(object);

遍历对象属性:

  • Object.getOwnPropertyNames 返回一个由对象属性名组成的数组(包含不可枚举的)
  • Object.keys 返回一个由对象可枚举的属性组成的数组.

Array API 增强

  • indexOf 返回某项内容在数组中的下标, 类同String.indexOf, 还有lastIndexOf
var arr = ['apple','orange','pear'];

console.log("found:", arr.indexOf("orange") != -1);
  • filter 遍历数组, 根据每次回调的return值, true保留, false过滤, 最终返回一个新数组
var arr = [
  {"name":"apple", "count": 2},
  {"name":"orange", "count": 5},
  {"name":"pear", "count": 3},
  {"name":"orange", "count": 16},
];

var newArr = arr.filter(function(item){
  return item.name === "orange";
});


console.log("Filter results:",newArr);
  • forEach 遍历数组, 每次回调中可以做一些操作
var arr = [1,2,3,4,5,6,7,8];

// Uses the usual "for" loop to iterate
for(var i= 0, l = arr.length; i< l; i++){
console.log(arr[i]);
}

console.log("========================");

//Uses forEach to iterate
arr.forEach(function(item,index){
console.log(item);
});
  • map 遍历数组, 根据每次回调的return值, 最终返回一个新数组
var oldArr = [{first_name:"Colin",last_name:"Toh"},{first_name:"Addy",last_name:"Osmani"},{first_name:"Yehuda",last_name:"Katz"}];

function getNewArr(){

  return oldArr.map(function(item,index){
    item.full_name = [item.first_name,item.last_name].join(" ");
    return item;
  });

}

console.log(getNewArr());
  • every 遍历数组, 根据每次回调的return值, 如果都为true, 则最终返回true, 反之最终返回false
var arr = [ 1, 2, 3, 4];
var result = arr.every( function( item, index, array ){
    console.log( item, index, array );
    return item < 3;
});

 1 0 [1, 2, 3, 4]
 2 1 [1, 2, 3, 4]
 3 2 [1, 2, 3, 4]

 result -> false
  • some 遍历数组, 根据每次回调的return值, 如果都为false, 则最终返回false, 反之最终返回true
var arr = [ 1, 2, 3, 4];
var result = arr.some( function( item, index, array ){
    console.log( item, index, array);
    return item > 2;
});
->
 1 0 [1, 2, 3, 4]
 2 1 [1, 2, 3, 4]
 3 2 [1, 2, 3, 4]

 restule -> true
  • reduce

reduce在这里有减少的意思,那reduce到底是干什么用的呢?说实话我也不太理解,看看比较官方的解释:The method applies a function against an accumulator and each value of the array (from left -to- right ) to reduce it to a single value . 自己慢慢的理解吧,我们先看看怎么使用吧,用的多了自然就明白了:

var arr = [1,2,3,4];
var newArr = arr.reduce(function(previousValue, currentValue, currentIndex, array){
    console.log(previousValue, currentValue,currentIndex);
    return previousValue + currentValue;
});

1 2 1
3 3 2
6 4 3

newArr -> 10

从运行结果看,initialValue参数指定了previousValue的初始值,更重要的是,这次数组是从第1个位置开始遍历,而不再是从第2个位置开始了。 现在回过头来,对照这两个例子,我相信你一定能够理解reduce的作用了。下面对于reduce的扩展会巩固你对reduce的理解:

if(!Array.prototype.reduce) {
   Array.prototype.reduce = function (callback, initialValue) {
        var previousValue = initialValue || this[0];//如果不指定intialValue,则默认为数组的第一个元素
        //如果不指定initialValue,i从1开始遍历,否则就从0开始遍历
        for (var i = initialValue?0:1; i < this.length; i++) {
            //previousValue 累加每一次返回的结果
            previousValue += callback(previousValue, this[i],i,this.toString());
        }
        return previousValue;
    }
}
  • reduceRight

reduce的作用完全相同,唯一的不同是,reduceRight是从右至左遍历数组的元素。