array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 JS高级程序设计之高级技巧 - 爱码网
sundjly

1. 安全的类型检测

// 安全类型检测
/* 检测是不是原生的函数 */
function isFunction(value) {
    return Object.prototype.toString.call(value) == "[object Function]";
}

 

2.作用域安全的构造函数

// 作用域安全的构造函数
function Person(name, age, job) {
    if (this instanceof Person) {
        this.name = name;
        this.age = age;
        this.job = job;
    } else {
        return new Person(name, age, job);
    }
}
var person1 = Person("sundily", 22, \'Software Engineer\');

 

3.惰性载入函数:表示函数执行的分支仅会发生一次 (主要用在浏览器的兼容上 做一次判断)两种实现方法:
  ● 函数被调用时再处理函数。在第一次调用的过程中,该函数就会被重新覆盖为另一个按合适方法执行的函数
  ● 在声明函数时就指定适当的函数。这样第一次调用函数就不会损失性能了,而在代码首次加载时会损失一点性能

/* 惰性载入函数  表示函数执行的分支仅会发生一次 */
// 原例
function createXHR() {
    if (typeof XMLHttpRequest != "undefined") {
        return new XMLHttpRequest();
    } else if (typeof ActiveXObject != "undefined") {
        if (typeof arguments.callee.activeXString != "string") {
            var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp"];
            for (var index = 0; index < versions.length; index++) {
                try {
                    new ActiveXObject(versions[index]);
                    arguments.callee.activeXString = versions[index];
                    break;
                } catch (error) {

                }

            }
        }
        return new ActiveXObject(arguments.callee.activeXString);
    } else {
        throw new Error("NO XHR object available");
    }
}

// 使用惰性函数之后
function createXHR() {
    if (typeof XMLHttpRequest != "undefined") {
        createXHR = function () {
            return new XMLHttpRequest();
        }
    } else if (typeof ActiveXObject != "undefined") {
        createXHR = function () {
            if (typeof arguments.callee.activeXString != "string") {
                var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp"];
                for (var index = 0; index < versions.length; index++) {
                    try {
                        new ActiveXObject(versions[index]);
                        arguments.callee.activeXString = versions[index];
                        break;
                    } catch (error) {
                        // skip
                    }
                }
            }
            return new ActiveXObject(arguments.callee.activeXString);
        };
    } else {
        createXHR = function () {
            throw new Error("no xhr object available");
        };
    }
    return createXHR();
}

// 第二种惰性函数    匿名的立即执行函数   返回匿名函数
var createXHR = (function () {
    if (typeof XMLHttpRequest != \'undefined\') {
        return function () {
            return new XMLHttpRequest();
        };
    } else if (typeof ActiveXObject != "undefined") {
        return function () {
            if (typeof arguments.callee.activeXString != "string") {
                var versions = ["MSXML2.XMLHttp", "MSXML2.XMLHttp.6.0"];
                for (var index = 0; index < versions.length; index++) {
                    try {
                        new ActiveXObject(versions[index]);
                        arguments.callee.activeXString = versions[index];
                        break;
                    } catch (error) {
                        // skip
                    }
                }
            }
            return new ActiveXObject(arguments.callee.activeXString);
        };
    } else {
        return function () {
            throw new Error("no xhr object available");
        };
    }
})();

 

4 函数绑定——一个将函数绑定到指定环境的函数 bind()

/* 函数绑定 */
var handler = {
message: "event handler",
handlerClick: function () {
alert(this.message);
}
};
var btn = document.getElementById("mybtn");
btn.addEventListener("click", handler.handlerClick.bind(handler), false);

只要是将某个函数指针以值的形式进行传递,同时该函数必须在特定环境中执行,就应该用函数绑定
主要应用与事件处理程序以及setInterval() setTimeout() 比普通函数需要更多的内存,所以最好必要时用

5 .函数柯里化(function currying)——用于创建已经设置好了一个或者多个参数的问题
函数柯里化基本方法和函数绑定时一样的,使用一个闭包返回一个函数
动态创建柯里化:调用另一个函数并为他传入要柯里化的函数和必要的参数

/* 函数柯里化:调用另一个函数并为他传入要柯里化的函数和必要的参数
主要工作 就是将返回函数的参数进行排序
concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。
*/
function curry(fn) {
var args = Array.prototype.slice.call(arguments, 1);//arguments中第一个参数时fn 所以要从1开始slice()
return function () {
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return fn.apply(null, finalArgs);//调用函数fn自己本身,apply的第一个参数就是null,finalArgs就是传入的参数
}
}

es5中bind()方法也实现了柯里化
// bind()的柯里化
var handler={
message:"event handler",
handlerClick:function(name,event){
alert(this.message+":"+name+":"+event.type);
};
}
var btn=document.getElementById("mybtn");
btn.addEventListener(\'click\',handler.handlerClick.bind(handler,"mybtn"));

 


6. 防篡改对象
  1. 不可扩展的对象

var person={name:"sundjly"};
Object.preventExtensions(person);//不能再给person添加属性和方法 但仍然可以修改 删除已有的成员
// 使用Object.isExtensible()方法确定对象是否可以扩展
Object.isExtensible(person);//false

    1. 1密封的对象(sealed object):密封对象不可扩展,而且已有属性方法不能删除,

Object.seal(person);
Object.isSealed(person);//判断对象是否被密封

    1.2冻结对象 Object.freeze(person);//无法对对象做出操作

7. 高级定时器:
js是单线程的,由代码队列先后顺序执行。js中没有任何代码是立即执行的,但一旦进程空闲则尽快执行。
setInterval:这种重复定时器的规则有两个问题:
    1. 某些间隔会被跳过
    2. 多个定时器的代码执行之间的间隔可能比预期小

/* 避免setInterval()重复定时器的两个缺点,可以使用链式setTimeout()调用
这个模式链式调用setTimeout()函数,每次函数执行的时候都会创建一个新的定时器,第二个setTimeout调用arguments.callee
获取当前函数的引用
优点:在前一个定时器代码执行之前,不会向队列插入新的定时器代码,确保不会有任何缺失的间隔,
而且它可以保证在下次定时器代码执行之前,至少等待间隔时间,避免了连续运行。
*/
setTimeout(function() {
// 处理函数
setTimeout(arguments.callee, interval);
}, interval);

具体的例子:

setTimeout(function () {
    var div = document.querySelector("#div");
    left = parseInt(div.style.left) + 5;
    div.style.left = left + "px";
    if (left < 200) {
        setTimeout(arguments.callee, 50);
    }
}, 50);

 

8.Yielding Processes
  1. 脚本长时间运行的的原因:
    a. 过长的,过深嵌套的函数调用
    b. 进行大量处理的循环
  2. 如果处理不必同步完成,数据不必按顺序完成,那么可以使用定时器分割循环——数组分块(array chunking)
    a. 基本思路:为要处理的项目创建一个队列,然后使用定时器取出下一个要处理的项目进行处理,接着在设置另一个定时器

/* 
数组分块技术:shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
array变量的本质就是一个“待办事宜”列表,包含要处理的列表
*/
setTimeout(function () {
    // 取出第一个条目并处理
    var item = array.shift();
    process(item);
    // 若还有条目,再设置定时器
    if (array.length > 0) {
        setTimeout(arguments.callee, 100);
    }
}, 100);

 

  3.

function chunk(array, process, context) {
    setTimeout(function () {
        var item = array.shift();
        process.call(context, item);
        if (array.length > 0) {
            setTimeout(arguments.callee, 100);
        }
    }, 100);
}

一旦某个函数需要花费50ms以上的时间完成,那么最好考虑能否将任务分割为一系列可以使用定时器的小任务


9 函数节流
DOM操作比起非dom操作交互需要更多的内存和CPU时间,连续尝试过多的DOM相关操作可能会导致浏览器挂起,崩溃。尤其是IE中onresize事件,为了绕开这个问题,可以使用定时器对该函数进行节流。
基本思路:代码可以在间断的情况下连续重复的执行,目的只有在执行函数的请求停止一段时间之后才执行:

/* 函数节流:
 */
var processor = {
    timeoutID: null,
    // 实际进行处理的方法
    performProcessing: function () {
        // 实际执行的代码
    },
    // 初始处理调用的方法
    process: function () {
        clearTimeout(this.timeoutID);
        var that = this;
        this.tomeoutID = setTimeout(function () {
            that.performProcessing();
        }, 100);
    }
};
// 尝试开始执行
processor.process();
// 简化
function throttle(method, context) {
    clearTimeout(method.tId);
    method.tId = setTimeout(function () {
        method.call(context);
    }, 100);
}
// 列子
function resizeDiv() {
    var div = document.querySelector("#div");
    div.style.height = div.offsetWidth + "px";
}
window.onresize = function () {
    throttle(resizeDiv);
}

 

只要代码是周期性执行的,都要用函数节流,控制处理的频率,确保浏览器不会再短时间内进行过多的计算

10 自定义事件:
事件——一种叫观察者的设计模式(创建松散耦合代码的技术)
观察者模式是由两类对象组成:主体和观察者。主体负责发布事件,观察者通过订阅这些事件来观察主体,在DOM中,DOM元素就是主体,你的事件处理程序就是观察者
事件是与DOM交互最常见的方式。
自定义事件的适用场景:当代码中存在多个部分在特定时刻互相交互的情况下

/* 自定义事件 */
function EventTarget() {
    this.handlers = {};
}
EventTarget.prototype = {
    constructor: EventTarget,
    addHandler: function (type, handler) {
        if (typeof this.handlers[type] == "undefined") {
            this.handlers[type] = [];
        }
        this.handlers[type].push(handler);
    },
    fire: function (event) {
        if (!event.target) {
            event.target = this;
        }
        if (this.handlers[event.type] instanceof Array) {
            var handlers = this.handlers[event.type];
            for (var index = 0; index < handlers.length; index++) {
                handlers[index](event);
            }
        }
    },
    removeHandler: function (type, handler) {
        if (this.handlers[type] instanceof Array) {
            var handlers = this.handlers[type];
            for (var index = 0; index < handlers.length; index++) {
                if (handlers[index] == handler) {
                    break;
                }
            }
            handlers.slice(index, 1);
        }
    }
};

function handleMessage(event) {
    alert("message received" + event.message);
}
var target = new EventTarget();
target.addHandler("message", handleMessage); //添加事件处理程序
target.fire({
    type: "message",
    message: "hello world"
}); //触发事件
target.removeHandler("message", handleMessage); //删除事件处理程序

 

12 拖放

/* 拖放
<div class="draggable" style="position:absolute; background:red;"></div>
*/
var DragDrop = function () {
// DragDrop对象封装了拖放的所有基本功能,这是一个单例,并使用了模块模式来隐藏某些实现细节 但是该方法没有提供任何方法表示拖动开始,正在拖动,或者已经结束
var dragging = null, //存放被拖动的元素
diffX = 0,
diffY = 0;

function handleEvent(event) {
// 获取事件目标
var target = event.target;
// 确定事件类型
switch (event.type) {
case "mousedown":
if (target.className.indexof("draggable") > -1) {
dragging = target;
diffX = event.clientX - target.offsetLeft;
diffY = event.clientY - target.offsetWidth;
}
break;
case "mousemove":
if (dragging != null) {
// 指定位置
dragging.style.left = (event.clientX - diffX) + "px";
dragging.style.top = (event.clientY - diffY) + "px";
}
break;
case "mouseup":
dragging = null;
break;

}
};
return {
enable: function () {
document.addEventListener("mousedown", handleEvent, false);
document.addEventListener("mousemove", handleEvent, false);
document.addEventListener("mouseup", handleEvent, false);
},
disable: function () {
document.removeEventListener("mousedown", handleEvent, false);
document.removeEventListener("mousemove", handleEvent, false);
document.removeEventListener("mouseup", handleEvent, false);
}
}
}();

 

分类:

技术点:

相关文章: