ECMASCRIPT 5 Object.keys

问题提出 我要获取一个对象包含属性的个数

在我们使用Javascript的过程中、我们经常把Object当做散列或者Map来使用。有时候我想知道一个对象当前存了多少东西,假设我要分析一下 图书馆里图书的数据 这里有个作者与对应图书的集合 ,这个对象包含了几项内容:如下

var bookAuthors = {
    "Farmer Giles of Ham": "J.R.R. Tolkien",
    "Out of the Silent Planet": "C.S. Lewis",
    "The Place of the Lion": "Charles Williams",
    "Poetic Diction": "Owen Barfield"
};

作为分析的一部分,我们像一个API发送图书作者的数据,不幸的是 这个API只能接受一个包含100本左右的图书对象,于是我们需要向一个号的解决方案,在向API发送之前想告诉它一共包含了多少本书。

解决方案,使用for in 变量所有属性,hasOwnProperty判断是不是属于当前对象本身的

于是最初的设计可能如下

function countProperties (obj) {
    var count = 0;

    for (var property in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, property)) {
            count++;
        }
    }

    return count;
}
var bookCount = countProperties(bookAuthors);
// Outputs: 4
console.log(bookCount);

之所以使用hasOwnProperty 是因为 for in 不但会对象本身的属性,同时也会遍历继承而来的属性 判断

Object.keys

当然这种 方案确实是可行的,那么如果能避免手工的计算属性的个数岂不是会更好,Javascript能不能直接获取呢。在ES5 中Object 有了一个 keys 属性是专门获取 对象属性的name并且返回一个数组。这里只返回这个对象本身的属性 不包含继承过来 ,作用等同于

  for (var property in obj) {
     if (Object.prototype.hasOwnProperty.call(obj, property)) {                      
    }
}

如果要获取一个对象属性的个数 获取Keys之后,通过数组的length属性就可以获取了。值得一提的是Object.keys(obj) ,只能通过这种方式,他是Object对象中的方法(有点是静态的意思),并不是在Object.prototype上的 因此我们自己定义的对象时没有这个方法的,所以正确的使用方式如下

var bookCount = Object.keys(bookAuthors).length;
// Outputs: 4
console.log(bookCount);

错误的使用方式

var bookCount = bookAuthors.keys().length; //会报错的,自己声明的对象时不具有这个方法的

其他-Object.getOwnPropertyNames

同时也是在ES5中 有个类似的方法 Object.defineProperties,两者也稍有区别

Object.keys 以及Object.getOwnPropertyNames()用来获取对象中的属性的name,不包括继承来的属性,两者区别是Object.keys 只能获取可遍历的属性的名字的数组。举个例子

 var person = {};
Object.defineProperties(person, 
    {
        "name": {value: 'Cody Lindley',enumerable: true},
        "age": {value: 38,enumerable: false}
    }
);
//只返回可以可遍历的属性 
console.log(Object.keys(person)); //logs ["name"]
//return array of all properties, including ones that are non-enumerable
console.log(Object.getOwnPropertyNames(person)); //returns ["name", "age"]

ployFill 为不支持ES5的浏览器提供支持

以下摘自es5-shim

   var hasDontEnumBug = true,
        hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'),
        dontEnums = [
            "toString",
            "toLocaleString",
            "valueOf",
            "hasOwnProperty",
            "isPrototypeOf",
            "propertyIsEnumerable",
            "constructor"
        ],
        dontEnumsLength = dontEnums.length;
    for (var key in {"toString": null}) {
        hasDontEnumBug = false;
    }
    Object.keys = function keys(object) {
        var isFunction = _toString(object) === '[object Function]',
            isObject = object !== null && typeof object === 'object';

        if (!isObject && !isFunction) {
            throw new TypeError("Object.keys called on a non-object");
        }

        var keys = [],
            skipProto = hasProtoEnumBug && isFunction;
        for (var name in object) {
            if (!(skipProto && name === 'prototype') && owns(object, name)) {
                keys.push(name);
            }
        }
        if (hasDontEnumBug) {
            var ctor = object.constructor,
                skipConstructor = ctor && ctor.prototype === object;
            for (var i = 0; i < dontEnumsLength; i++) {
                var dontEnum = dontEnums[i];
                if (!(skipConstructor && dontEnum === 'constructor') && owns(object, dontEnum)) {
                    keys.push(dontEnum);
                }
            }
        }
        return keys;
    };

}

Phonegap创建移动应用

前段时间学习了Phonegap开发,本篇作为记录,希望对初道者有帮助,本篇主要介绍Phonegap以及环境的搭建。下篇结合Angluar 开发小Demo

Phonegap介绍

Phonegap 作为一个开源的框架来帮助开发者使用Javascript/HTML5/CSS 开发跨平台的移动应用。他可以根据指定的移动平台打包为对应的包,支持的平台种类如下。

  • iOS
  • Android
  • Windows 8
  • Windows Phone 7 and 8
  • BlackBerry 5.x+
  • WebOS
  • Symbian
  • Tizen
  • Firefox OS(3.4版本开始支持的)

插件

Phonegap 本质上是在本地原生应用程序中包裹了一个Webview 来支持使用HTML5 进行开发。但是这种方式本质上是不支持访问设备的功能,比如访问文件系统,或者照相机,但是Phonegap通过桥接机制允许Webview中的Javascript 来调用原生的代码,于是Phonegap就拥有了许多插件来支持访问设备API比如

  • 加速度计
  • 相机
  • 联系人
  • 文件系统
  • 媒体文件的播放 以及录音
  • 网络
  • 存储

同时Phonegap 可以允许开发者通过扩展插件来访问更多的设备API比如

  • 二维码扫描
  • 蓝牙
  • 推送通知
  • 语音合成
  • 日历

在之前版本的Phonegap中 包括了一些预编译的插件。随着Phonegap 3的到来,一个新的插件架构取代了原来的插件访问。同时有一个注册中心来创建兼容Phonegap 3的插件

HTML/CSS /Javascript 移动开发基础。

Phonegap本身提供的大部分功能是提供了一些非可视化的功能组件,比如访问文件系统,网络能力,地理定位,等等。Phonegap本身并没有提供构建图形界面的能力,对于此,我们必须使用HTML、CSS来构建,为了更方便地开发中应用,因此推荐结合JS 框架来进行组织程序的开发。这些框架包括

  • jQuery Mobile
  • Ionic
  • Sencha Touch
  • Kendo UI Complete
  • AppGyver’s Steroids
  • Enyo
  • TopCoat

jQuery Mobile 这个就不用说了,简单理解Jquery的移动版本,AngluarJS 是一个比较火的MMV框架,Ionic也是AngluarJS构建的,这里我采用的是AngluarJs。开发之前还要了解一下面的这个问题。

####PhoneGap Or Cordova的关系

在学习Phonegap的过程中,我们经常会碰到Cordova 这个词,事实上,我们使用命令行工具创建的Phonegap工程其实是Cordova,。Cordova是贡献给Apache后的开源项目,是从PhoneGap中抽出的核心代码,是驱动PhoneGap的核心引擎。Cordova提供了一组设备相关的API,通过这组API,移动应用能够以JavaScript访问原生的设备功能,如摄像头、麦克风等。
Cordova还提供了一组统一的JavaScript类库,以及为这些类库所用的设备相关的原生后台代码。你可以把他想象成类似于Webkit和Google Chrome的关系。在大部分情况下这两个名字是可以交换的,随着Phonegap作为Adobe的商标,这个开源的项目需要一个新的名字,因此就有了Cordova,Phonegap继续作为Adobe的商业产品,大部分仍然将这个整体的项目称为Phonegap。

Phonegap 开发环境搭建。

这里我要基于Phonegap开发能够运行在android上的程序。

建环境的基本准备:

  1. java JDK、配置Java环境变量
  2. 下载android ADT Bundle(里面是一个继承了安卓开发环境的Eclipse),下载之后将android SDK下的tools的目录添加到环境变量中,启动下载包里面的eclipse 创建AVD
  3. Ant 打包工具(windows 下载推荐下载 winant)
  4. NodeJS
  5. 安装phonegap

    npm install -g cordova
    

    或者

    npm install -g phonegap
    

    cordova和phonegap这两个命令是通用的。npm install -g phonegap 是3.0之后的新出的一种安装方式,这里我使用是phonegap。

创建Helloword

在命令行下运行

phonegap create my-app
cd my-app
phonegap run android

如果有android 设备连接了电脑的话,这时候会自动将应用部署到设备上,如果没有设备的话,会自动启用刚才创建的模拟器(注意 前面配置过程中一定要把android SDK下的tool 目录添加到环境变量中,并且确保已经创建了模拟器(AVD))到此为止一个Phonegap 版本的Hello World 已经开发完毕。

下面看进入my-app的目录,进入之后我们发现有5个文件夹

  • www : 文件夹 开发的 HTML5 ; CSS ; JS 文件都拷贝到这下面,以后我们开发HTML5的应用主要在这个文件夹下进行
  • plugins : 文件夹 存放的是phonegap插件比如文件,摄像头等插件都下载到这里。
  • merges : (这个我还不了解)
  • platforms : 文件夹 存放的是编译好后的android文件,(如果这个文件夹为空,需要你在命令行编译一次才能生成. 如上面 phonegap run android)
  • .cordova : 存放的是配置文件 。

将这个工程 导入到 Eclipse 下可以查看更多的工程信息。