闲谈 node (初探)

以前编写js的时候,总是在各种浏览器之间纠结,有时纠结兼容性问题,有时纠结性能或效率,很多时候看着后端工程师玩弄着各种数据心里就痒痒,只能感叹,js不给力。

不过在这一切都是浮云的世界,什么都在变,就和打麻将一样,风水轮流转,无论是Python还是Ruby,无论是BigTable或是Dynamo,就连CPU都尼玛从双核到四核,甚至把“显卡”也集成进去了,咱们的JS也应该发光发热了吧?

是的,一切都很给力,node就是这样,它就这样诞生了。

node,一个JS的运行环境,一个放在服务器上的JS运行环境,没错,他不是放在浏览器上,他是能像PHP一样跑在服务器上的运行环境。:)

我看到面前的PHP工程师笑了,我看到各位写C的同学笑了,好吧,正所谓拉车的用马,碾磨的用驴,面对日渐庞大的网络应用环境,面对无数用JS支撑起来的交互效果,面对数以万计想用JS干掉PHP的前端同学,让我们深究一下node究竟给不给力吧。

言归正传,无论是7天学会PHP还是7天学会C++第一步都是从“Hello World”,哦,不,是从安装环境开始,我们也入乡随俗,从这儿开始。

官方安装说明(https://github.com/joyent/node/wiki/Installation

主要内容如下

git clone https://github.com/joyent/node.git
cd node
export JOBS=2 # optional, sets number of parallel commands.
mkdir ~/local
./configure --prefix=$HOME/local/node
make
make install
export PATH=$HOME/local/node/bin:$PATH

根据中国特色我们需要注意:
1、确认你的系统为Linux,Mac或者Solaris,如果你试图在Windows或者Unix上安装如果你试图在Windows或者Unix(除Mac OS外)上安装,请先尝试安装编译环境,可百度,一定很多。
2、安装libssl-dev和python,通常情况下他们都有。
3、如果是Mac,需要安装Xcode。
4、你也可以通过包管理器进行安装(https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager),看到这里我吐了。。。
5、因为最近墙有问题,所以大部分时候Git都很慢,请耐心等待或者翻墙。

好,现在我们

node -v

看看是否成功了吧!

行了,到这里我们基本上就准备完成了,可以执行国际惯例,HelloWorld了。

console.log('hello world');

前端同学一定惊呼,我x,好熟悉啊,这不是我们经常在firebug里面用的console么?是的,node使用console来输出调试,当然如果你喜欢步进调试,喜欢逆向工程中不断的下断点来调试,你可以尝试Qleelulu这样帅气的debug,虽然我认为这样非常低效。 :-)

好了,现在可以运行也可以调试了,我和同学们都兴奋了,我要写个百度乐居(AD),我要写个新浪微博(AD),我要写个淘宝(AD),我X,我怒吼,不要慌!俗话说得好,工欲善其事,必先利其器,让我们看看nodeJS的wiki上还有什么?

nom(node package manager)
npm 是基于 node 的包管理器,通过npm,我们可以很容易的安装其它基于node的扩展
官网地址:https://github.com/isaacs/npm
安装npm很简单,一句话

curl http://npmjs.org/install.sh | sh

通常情况下这样是可以安装成功,但是我在Mac上这样安装总是失败,如果不幸的你也失败可参考下面的安装方式

git clone http://github.com/isaacs/npm.git
cd npm
sudo make install

Linux下很顺利,一次成功!

备注:
查找npm提供的包有两种方式,第一种是通过”npm find”命令查找,第二种可通过http://search.npmjs.org/查找。

让我们从node 的 modules list页面中选择一个框架(https://github.com/joyent/node/wiki/modules
为了简便开发,通常我们都会选择一个框架,就像Zend或者Rails一样,这里我选择的是Express,因为大家都说好。。。
Express官网:http://expressjs.com/

Express的安装非常简单,借助我们刚才安装的npm,既可直接安装了

npm install express

安装完毕之后,在开发目录下存在一个node_modules的文件夹用来存放这些扩展。
接下来,我们就可以使用express来开发写一个可以运行在浏览器上的Hello World了

var express = require('express');
var app = express.createServer();
 
app.get('/', function(req, res){
    res.send('Hello World');
});
 
app.listen(3000);

然后访问本地http://127.0.0.1:3000/
好了,世界再一次被问好了。

至此,我们的准备工作已经完成,下一篇我们准备写点什么吧!

原文链接(348 views)|评论 (5)

构造函数(constructor)的超类

  function test1( name ){
    this.name = name;
  }
 
  function test2( name ){
    test1.call(this,name);
    this.say = function(){}
  }
 
  test2.prototype = new test1;
 
  var t = new test2("nihao");
 
  console.log(t);
  console.log(t.constructor);

t的constructor说明了t的构造函数是test1,而不是test2。

这是因为t的constructor实际上是test2.prototype的constructor,而test2.prototype = new test1;因此test2test2.prototype的constructor属性就指向到了test1的prototype.constructor上test1.prototype的constructor上,也就是test1。

罗里吧嗦的,这标题起的还挺唬人的~呵呵

原文链接(76 views)|沙发已被占领(1)

Javascript File API for Mozilla

1. 文件读取函数
readAsBinaryString() 读取文件内容,读取结果为一个 binary string。文件每一个 byte 会被表示为一个 [0..255] 区间内的整数。函数接受一个 File 对象作为参数。
readAsText() 读取文件内容,读取结果为一串代表文件内容的文本。函数接受一个 File 对象以及文本编码名称作为参数。
readAsDataURL 读取文件内容,读取结果为一个 data: 的 URL。DataURL 由 RFC2397 定义,具体可以参考 http://www.ietf.org/rfc/rfc2397.txt。

2. 文件读取事件
Onloadstart 文件读取开始时触发。
Progress 当读取进行中时定时触发。事件参数中会含有已读取总数据量。
Abort 当读取被中止时触发。
Error 当读取出错时触发。
Load 当读取成功完成时触发。
Loadend 当读取完成时,无论成功或者失败都会触发。

<form name="demoForm" id="demoForm" method="post" enctype="multipart/form-data" 
onsubmit="uploadAndSubmit();return false;"> 
<p>Upload File: <input type="file" name="file" /></p> 
<p><input type="submit" value="Submit" /></p> 
</form> 
<div>Progessing (in Bytes): <span id="bytesRead"> 
</span> / <span id="bytesTotal"></span> 
</div>
  function uploadAndSubmit() {
    var form = document.forms["demoForm"]; 
 
     if (form["file"].files.length > 0) {
     // 寻找表单域中的 <input type="file" ... /> 标签
     var file = form["file"].files[0];
     // try sending
     var reader = new FileReader(); 
 
     C.log(reader);
     reader.onloadstart = function() {
     // 这个事件在读取开始时触发
     C.log("onloadstart");
     document.getElementById("bytesTotal").textContent = file.size;
     }
     reader.onprogress = function(p) {
     // 这个事件在读取进行中定时触发
     C.log("onprogress");
     document.getElementById("bytesRead").textContent = p.loaded;
     } 
 
     reader.onload = function() {
        // 这个事件在读取成功结束后触发
        console.log("load complete");
     } 
 
     reader.onloadend = function() {
        // 这个事件在读取结束后,无论成功或者失败都会触发
     if (reader.error) {
        C.log(reader.error);
     } else {
        document.getElementById("bytesRead").textContent = file.size;
        C.log(reader.readyState);
     }
     } 
 
        reader.readAsBinaryString(file);
     } else {
        C.log("请选择上传文件");
     }
    }
 
    var C = {
    // console wrapper
    debug: true, // global debug on|off
    quietDismiss: false, // may want to just drop, or alert instead
    log: function() {
        if (!C.debug) return false;
 
        if (typeof console == 'object' && typeof console.log != "undefined") {
            console.log.apply(this, arguments);
        }
        else {
            if (!C.quietDismiss) {
                var result = "";
                for (var i = 0, l = arguments.length; i < l; i++)
                    result += arguments[i] + " ("+typeof arguments[i]+") ";
 
                var elem = document.createElement("textarea");
                elem.innerHTML = result;
				document.body.appendChild(elem);
                }
            }
        }
    }; // end console wrapper.

fileAPI Demo:fileAPI.zip

原文链接(170 views)|暂无评论(赶紧抢沙发)

函数的生成

function create(fun,proto){
    var f=function(){};
    //Copy the object since it is going to be changed.
    for (var x in proto){
        f.prototype[x] = proto[x];
    }
    f.prototype.toString = fun;
    return new f;
}
var fun=function(){alert("a");return "Hello world";}
var obj={x:5}
 
var foo=create(fun,obj);
alert(foo); //Hello world
foo.x=8;
alert(foo.x); // 8
delete foo.x;
alert(foo.x); // 5

原文链接(56 views)|评论 (2)

jQuery inViewport

晚上在微博上“拔赤”写了个lazyload插件,发现其中用到一个很有意思的方法”div.inViewportRegion()”,字面意思就是在可视区域内。

在网上找了找,发现这是YUI提供的一个组件,觉得很有意思。
http://gillserver.com/yui/api/dom-region.js.html

如果jQ里面也包含类似的方法,可以做很多事,于是GG了一下,发现国外的同学写过这种选择器,代码表现上更直观。

代码如下:

(function($) {
 
    $.belowthefold = function(element, settings) {
        var fold = $(window).height() + $(window).scrollTop();
        return fold < = $(element).offset().top - settings.threshold;
    };
 
    $.abovethetop = function(element, settings) {
        var top = $(window).scrollTop();
        return top >= $(element).offset().top + $(element).height() - settings.threshold;
    };
 
    $.rightofscreen = function(element, settings) {
        var fold = $(window).width() + $(window).scrollLeft();
        return fold < = $(element).offset().left - settings.threshold;
    };
 
    $.leftofscreen = function(element, settings) {
        var left = $(window).scrollLeft();
        return left >= $(element).offset().left + $(element).width() - settings.threshold;
    };
 
    $.inviewport = function(element, settings) {
        return !$.rightofscreen(element, settings) && !$.leftofscreen(element, settings) && !$.belowthefold(element, settings) && !$.abovethetop(element, settings);
    };
 
    $.extend($.expr[':'], {
        "below-the-fold": function(a, i, m) {
            return $.belowthefold(a, {threshold : 0});
        },
        "above-the-top": function(a, i, m) {
            return $.abovethetop(a, {threshold : 0});
        },
        "left-of-screen": function(a, i, m) {
            return $.leftofscreen(a, {threshold : 0});
        },
        "right-of-screen": function(a, i, m) {
            return $.rightofscreen(a, {threshold : 0});
        },
        "in-viewport": function(a, i, m) {
            return $.inviewport(a, {threshold : 0});
        }
    });
 
})(jQuery);

来源:http://www.appelsiini.net/projects/viewport

简单测了下,不错,呵呵~

Demo:http://www.zhangjingwei.com/inviewport.zip

原文链接(104 views)|暂无评论(赶紧抢沙发)