首页 > 网站 > WEB开发 > 正文

Javascript 语言精粹 代码片段合集

2024-04-27 14:12:00
字体:
来源:转载
供稿:网友

javascript 语言精粹 代码片段合集

Javascript 语言精粹 代码片段合集

标签:Douglas-Crockford Javascript 最佳实践


原文链接更好的阅读体验

使用一个method 方法定义新方法
Function.PRototype.method = function (name, func) {    if (!this.prototype[name]) {        this.prototype[name] = func;    }    return this;}

根据数字的正负来判断是使用Math.ceiling 还是Math.floor
Number.method("integer", function () {    return Math[this < 0 ? 'ceil' : 'floor'](this);});

移除字符串首尾的空白
String.method("trim", function () {    return this.replace(/^/s+|/s+$/g, '');})

闭包演示
var myObject = (function () {    var value = 0;    return {        increment: function (inc) {            value += typeof inc === "number" ? inc : 1;        },        getValue: function () {            return value;        }    };}());

缓存中间计算结果 - 斐波纳挈数组
// 定义var memoizer = function (memo, formula) {    var recur = function (n) {        var result = memo[n];        if (typeof result !== 'number') {            result = formula(recur, n);            memo[n] = result;        }        return result;    };    return recur;};// 使用var fibonacci = memoizer([0, 1], function (recur, n) {    return recur(n-1) + recur(n - 2);});for (var i = 0; i <= 10; i++) {    console.log("%d : %d", i, fibonacci(i));}// 扩展用法 阶乘var factorial = memoizer([1, 1], function (recur, n) {    return n * recur (n - 1)});for (var i = 1; i <= 10; i++) {    console.log("%d : %d", i, factorial(i));}

如何实现继承 - 函数化
  1. 创建一个对象
  2. 有选择地定义私有实例变量和方法。这些就是函数中通过var语句定义的普通变量
  3. 给这个新对象扩充方法。这些方法拥有特权去访问参数,以及上一步中定义的变量。
  4. 返回这个新对象
// 这里是一个函数化构造器的伪代码模板(加粗的文本表示强调):var **constructor** = function (spec, my) {    // 代码快内部不知道怎么加粗,哪位大神指点一下    var that, **其他私有变量**;    my = my || {};    // **把共享的变量和函数添加到my中**    that = {        name: "**一个新对象**"    };    // **给that添加特权方法**    return that;}// spec 对象包含构造器需要构造一个新实例的所哟信息。spec 的内容可能会被复制到私有变量中,或者被其他函数改变,或者方法可以在需要的时候访问spec的信息。(一个简化的方式是替换spec为一个单一的值。当构造对象过程中并不需要整个spec对象的时候,这是有用的。)// my 对象是一个为继承链中的构造器提供秘密共享的容器。my对象可以选择性地使用。如果没有传入一个my对象,那么会创建一个my对象// demovar mammal = function (spec) {    var that = {};    that.get_name = function () {        return spec.name;    };    that.says = function () {        return spec.saying || "";    }    return that;};var cat = function (spec) {    spec.saying = spec.saying || 'meow';    var that = mammal(spec);    that.purr = function (n) {        var i, s = '';        for (i = 0; i < n; i += 1) {            if (s) {                s += "-";            }            s += "r";        }        return s;    };    that.get_name = function () {        return that.says() + " " + spec.name + " " + that.says();    };    return that;};var myCat = cat({name: "Henrietta"});
函数化模式还提供了一个处理父类方法的方法。我们会构造一个superior方法,它取得一个方法名并返回调用那个方法的函数。该函数会调用原来的方法,尽管属性已经变化了。
Object.method('superior', function (name) {    var that = this,        method = that[name];    return function () {        return method.apply(that, arguments);    };});

让我们在coolcat上试验一下,coolcat就像cat一样,除了它有一个更酷的调用父类方法的get_name方法。它只需要一点点的准备工作。我们会声明一个super_get_name变量,并且把调用superior方法所返回的结果赋值给它。

var coolcat = function (spec) {    var that = cat(spec),        super_get_name = that.superior('get_name');    that.get_name = function (n) {        return 'like ' + super_get_name() + ' baby';    };    return that;};var myCoolCat = coolcat({name: 'Bix'});var name = myCoolCat.get_name();console.log(name); // "like meow Bix meow baby"

部件

我们可以从一套部件中把对象组装出来。例如,我们可以构造一个给任何对象添加简单事件处理特性的函数。他会给对象添加一个on方法、一个fire方法和一个私有的事件注册表对象:

var eventuality = function (that) {    var registry = {};    that.fire = function (event) {        // 在一个对象上触发一个事件。该事件可以是一个包含事件名称的字符串        // 或者是一个拥有包含事件名称的 type 属性的对象。        // 通过'on'方法注册的事件处理程序中匹配事件名称的函数将被调用。        var array,            func,            handler,            i,            type = typeof event === 'string' ? event : event.type;        if (registry.hasOwnProperty(type)) {            array = registry[type];            for (i = 0; i < array.length; i += 1) {                handler = array[i];                // 每个处理程序包含一个方法和一组可选的参数。                // 如果该方法是一个字符串形式的名字,那么寻找到该函数。                func = handler.method;                if (typeof func === 'string') {                    func = this[func];                }                // 调用一个处理程序。如果该条目包含参数,那么传递它们过去。否则,传递该事件对象。                func.apply(this, handler.parameters || [event]);            }        }        return this;    };    that.on = function (type, method, parameters) {        // 注册一个事件。构造一条处理程序条目。将它插入到处理程序数组中,        // 如果这种类型的事件还不存在,就构造一个。        var handler = {            method: method,            parameters: parameters        };        if (registry.hasOwnProperty(type)) {            registry[type].push(handler);        } else {            registry[type] = [handler];        }        return this;    };    return that;};

我们可以在任何单独的对象上调用eventuality, 授予它事件处理方法。我们也可以赶在that被返回之前在一个构造器函数中调用它 eventuality(that);

eventuality(myCoolCat);myCoolCat.health = 100;myCoolCat.on('dead', function (event) {    var date = event.date;    var killer = event.killer;    console.log("%s killed me at %s", killer, date);});myCoolCat.on('hurt', function () {    this.health -= 50;    if (this.health <= 0) {        var event = {            type: 'dead',            killer: 'stone from sky',            date: new Date()        };        this.fire(event);    } else {        console.log('nothing, who is the strong guy.');    }});myCoolCat.fire("hurt"); //nothing, who is the strong guy.myCoolCat.fire("hurt"); //stone from sky killed me at Sat Mar 14 2015 15:47:29 GMT+0800 (CST)

数组与对象

javascript 编程中,一个常见的错误是在必须使用数组时使用了对象,或者在必须使用对象时使用了数组。其实规则很简单:当属性名是小而连续的整数时,你应该使用数组。否则,使用对象。javascript 本身没有一个好的机制来区分数组和对象。我们可以通过定义自己的is_array函数来弥补这个缺陷:

var is_array = function (value) {    return value        && typeof value === 'object'        && value.constructor === Array;};// 不过该方法在识别从不同的窗口(window)或者frame里构造的数组时会失败。下面是一个更好的方式// 上面这句话这里本人尚未理解,请高手指点var is_array = function (value) {    return Object.prototype.toString.apply(value) === '[object Array]';};
为数组扩充reduce函数
Array.method('reduce', function (f, value) {    var i;    for (i = 0; i < this.length; i += 1) {        value = f(this[i], value);    }    return value;});// DEMOvar data = [4, 8, 15, 16, 23, 42];var add = function (a, b) {    return a + b;};var mult = function (a, b) {    return a * b;};var sum = data.reduce(add, 0);console.log(sum);// 108var product = data.reduce(mult, 1);console.log(product); // 7418880// 因为数组其实就是对象,所以我们可以直接给一个单独的数组添加方法data.total = function () {    return this.reduce(add, 0);};var total = data.total();console.log(total); // 108
为数组指定初始值
Array.dim = function (dimension, initial) {    var a = [], i;    for (i = 0; i < dimension; i += 1) {        a[i] = initial;    }    return a;};var myArray = Array.dim(10, 0); //[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]// 注意这里不能使用我们之前说的method方法,应为那个方法是给某个类型的每一个具体的对象增加方法的,而这里我们是给Array这个 类型 增加方法,类似于某些静态语言中的静态方法或者类方法
数组排序

sort 方法会array中的内容进行排序。但是它不能正确第给

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表