zoukankan      html  css  js  c++  java
  • 《JavaScript高级程序设计》心得笔记-----第五篇章

    第二十二章

    1、  安全的检测是使用:Object.prototype.toString.call(value);

    eg:

    function isArray(value){
    
      return Object.prototype.toString.call(value) == “[object  Array]”;
    
    }

    PS:JSON的:

      

      var  isNativeJSON ==windoe.JSON && Object.prototype.toString.call(JSON) == “[object  JSON]”;

    2、  作用安全域的构造函数:(不然this会指向window)

    function Person(name,age){
    
    if(this instanceof Person){
    
        this.name = name;
    
        this.age = age;
    
    }
    
    else{
    
       return new Person(name,age);
    
    }
    
    }

    PS:使用作用安全域的构造函数,就会锁定调用构造函数的环境,如果使用构造函数窃取模式的继承而且不使用原形链,这个继承就有可能被破坏掉

    当一个构造函数(Student)继承一个使用作用安全域的构造函数的时候,里面要使用Person.call(this,”ccl”,23);来继承,但是还需要在这个函数下面使用

    Student.prototype = new Person();

    3、  惰性载入函数:

    1)   函数被调用时在处理函数(重写函数)【函数名 = function(){//代码}】

    2)   在声明函数时就指定适当的函数【return function(){//代码}】

    4、  函数绑定【创建一个函数,在特定的this环境中以指定参数调用另一个函数,通常与回调函数与事件处理程序一起使用】

    var handler = {
    message: "Event handled",
    handleClick: function(event){
    alert(this.message);
    }
    };

    1)   自己创建bind()

    (1)  创建一个bind()函数接受一个函数和一个环境,并返回给定环境中调用给定函数,并且将所有参数原封不动传递过去

    function bind(fn,context){
    
       return function(){
    
         return fn.apply(context,argument);
    
    }
    
    }

    (2)  调用EventUtil.addHandler(btn, "click", bind(handler.handleClick, handler));

    2)   利用原生的bind()方法:EventUtil.addHandler(btn, "click", handler.handleClick.bind(handler));

    5、  函数柯里化【使用一个闭包返回一个函数】

    1)   创建柯里化的通用方式

    function curry(fn){
    var args = Array.prototype.slice.call(arguments, 1);//1表示返回数组包含从第二个参数开始 的所有参数
    
    return function(){
    var innerArgs = Array.prototype.slice.call(arguments);
    var finalArgs = args.concat(innerArgs);
    return fn.apply(null, finalArgs);
    };
    }

          调用:var curriedAdd = curry(add, 5);//这里的add后面可以添加多个参数

    2)   作为函数绑定的一部分包含在其中,创造出更复杂的bind()函数

    function bind(fn, context){
    var args = Array.prototype.slice.call(arguments, 2);
    return function(){
    var innerArgs = Array.prototype.slice.call(arguments);
    var finalArgs = args.concat(innerArgs);
    return fn.apply(context, finalArgs);
    };
    }

    使用:EventUtil.addHandler(btn, "click", bind(handler.handleClick, handler, "my-btn"));

    3)   利用原生的bind()方法:

    EventUtil.addHandler(btn, "click", handler.handleClick.bind(handler, "my-btn"));

    6、  防篡改对象(一旦把属性把属性定义为防篡改就无法撤销了)

    1)   不可扩展对象:Object.preventExtensions(person);

    判断是否可以扩展:Object.isExtensible (person)

    2)   密封的对象【密封对象不可扩展,而且configuraable会设置为false,也就是不能删除属性和方法,但是属性值是可以修改的,在非严格模式下,删除和修改属性会被忽略,但是在严格模式下,会抛出错误】

    Object.seal(person);

    判断是否被密封:Object.isSealed (person)

    3)   冻结对象【既不可以扩展,又是密封的,而且对象的writable被设置为false,,在非严格模式下,对冻结的对象执行非法操作会被忽略,但是在严格模式下,会抛出错误】

    Object.Froze(person);

    判断是否被冻结:Object. isFrozen (person)

    7、  高级定时器

    重复定时器:链式 setTimeout()调用。

    setTimeout(function(){
    //处理中
    setTimeout(arguments.callee, interval);
    }, interval);

    8、  Yielding Processes

    1)   数组分块

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

    9、  函数节流

    function throttle(method, context) {
    clearTimeout(method.tId);
    method.tId= setTimeout(function(){
    method.call(context);
    }, 100);
    }

    10、自定义事件

    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 i=0, len=handlers.length; i < len; i++){
    handlers[i](event);
    }
    }
    },
    removeHandler: function(type, handler){
    if (this.handlers[type] instanceof Array){
    var handlers = this.handlers[type];
    for (var i=0, len=handlers.length; i < len; i++){
    if (handlers[i] === handler){
    break;
    }
    }
    handlers.splice(i, 1);
    
    }
    }
    };

    使用:

    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);
    //再次,应没有处理程序
    target.fire({ type: "message", message: "Hello world!"});

    2)   其他对象可以继承 EventTarget 并获得这个行为:

    function Person(name, age){
    EventTarget.call(this);
    this.name = name;
    this.age = age;
    }
    inheritPrototype(Person,EventTarget);
    Person.prototype.say = function(message){
    this.fire({type: "message", message: message});
    };

    11、拖放:

    var DragDrop = function(){
    var dragdrop = new EventTarget(),
    dragging = null,
    diffX = 0,
    diffY = 0;
    function handleEvent(event){
    //获取事件和对象
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    //确定事件类型
    
    switch(event.type){
    case "mousedown":
    if (target.className.indexOf("draggable") > -1){
    dragging = target;
    diffX = event.clientX - target.offsetLeft;
    diffY = event.clientY - target.offsetTop;
    dragdrop.fire({type:"dragstart", target: dragging,
    x: event.clientX, y: event.clientY});
    }
    break;
    case "mousemove":
    if (dragging !== null){
    //指定位置
    dragging.style.left = (event.clientX - diffX) + "px";
    dragging.style.top = (event.clientY - diffY) + "px";
    //触发自定义事件
    dragdrop.fire({type:"drag", target: dragging,
    x: event.clientX, y: event.clientY});
    }
    break;
    case "mouseup":
    dragdrop.fire({type:"dragend", target: dragging,
    x: event.clientX, y: event.clientY});
    dragging = null;
    break;
    }
    };
    //公共接口
    dragdrop.enable = function(){
    EventUtil.addHandler(document, "mousedown", handleEvent);
    EventUtil.addHandler(document, "mousemove", handleEvent);
    EventUtil.addHandler(document, "mouseup", handleEvent);
    };
    dragdrop.disable = function(){
    EventUtil.removeHandler(document, "mousedown", handleEvent);
    EventUtil.removeHandler(document, "mousemove", handleEvent);
    EventUtil.removeHandler(document, "mouseup", handleEvent);
    };
    return dragdrop;
    }();

    第二十三章

    1、  离线检测:navigator.onLine【true能上网,反之,但是不同浏览器之间还是有些差异】

    确定网络是否可用:online 和 offline

    EventUtil.addHandler(window, "online", function(){
    alert("Online");
    });
    EventUtil.addHandler(window, "offline", function(){
    alert("Offline");
    });

    在页面加载后,最好先通过 navigator.onLine 取得初始的状态。然后,就是通过上述两个事件来确定网络连接状态是否变化

    2、  应用缓存(appcache):applicationCache()对象

    3、  Cookie:名称和值都必须经过URL编码【decodeURIComponent()来解码】

    1)   读取、写入、删除

    var CookieUtil = {
    get: function (name){
    var cookieName = encodeURIComponent(name) + "=",
    cookieStart = document.cookie.indexOf(cookieName),
    cookieValue = null;
    if (cookieStart > -1){
    var cookieEnd = document.cookie.indexOf(";", cookieStart);
    if (cookieEnd == -1){
    cookieEnd = document.cookie.length;
    }
    cookieValue = decodeURIComponent(document.cookie.substring(cookieStart
    + cookieName.length, cookieEnd));
    }
    return cookieValue;
    },
    set: function (name, value, expires, path, domain, secure) {
    var cookieText = encodeURIComponent(name) + "=" +
    encodeURIComponent(value);
    if (expires instanceof Date) {
    cookieText += "; expires=" + expires.toGMTString();
    }
    if (path) {
    cookieText += "; path=" + path;
    }
    
    if (domain) {
    cookieText += "; domain=" + domain;
    }
    if (secure) {
    cookieText += "; secure";
    }
    document.cookie = cookieText;
    },
    unset: function (name, path, domain, secure){
    this.set(name, "", new Date(0), path, domain, secure);
    }
    };

    使用:

    //设置 cookie
    CookieUtil.set("name", "Nicholas");
    CookieUtil.set("book", "Professional JavaScript");
    //读取 cookie 的值
    alert(CookieUtil.get("name")); //"Nicholas"
    alert(CookieUtil.get("book")); //"Professional JavaScript"
    //删除 cookie
    CookieUtil.unset("name");
    CookieUtil.unset("book");
    
    //设置 cookie,包括它的路径、域、失效日期
    CookieUtil.set("name", "Nicholas", "/books/projs/", "www.wrox.com",
    new Date("January 1, 2010"));
    //删除刚刚设置的 cookie
    CookieUtil.unset("name", "/books/projs/", "www.wrox.com");
    //设置安全的 cookie
    CookieUtil.set("name", "Nicholas", null, null, null, true);

    2)   子cookie

    var SubCookieUtil = {
    get: function (name, subName){
    var subCookies = this.getAll(name);
    if (subCookies){
    return subCookies[subName];
    } else {
    return null;
    }
    },
    getAll: function(name){
    var cookieName = encodeURIComponent(name) + "=",
    cookieStart = document.cookie.indexOf(cookieName),
    cookieValue = null,
    cookieEnd,
    subCookies,
    i,
    parts,
    result = {};
    if (cookieStart > -1){
    cookieEnd = document.cookie.indexOf(";", cookieStart);
    if (cookieEnd == -1){
    cookieEnd = document.cookie.length;
    }
    cookieValue = document.cookie.substring(cookieStart +
    
    cookieName.length, cookieEnd);
    if (cookieValue.length > 0){
    subCookies = cookieValue.split("&");
    for (i=0, len=subCookies.length; i < len; i++){
    parts = subCookies[i].split("=");
    result[decodeURIComponent(parts[0])] =
    decodeURIComponent(parts[1]);
    }
    return result;
    }
    }
    return null;
    },
    //省略了更多代码
    };

    使用:

    //假设 document.cookie=data=name=Nicholas&book=Professional%20JavaScript
    //取得全部子 cookie
    var data = SubCookieUtil.getAll("data");
    alert(data.name); //"Nicholas"
    alert(data.book); //"Professional JavaScript"
    //逐个获取子 cookie
    alert(SubCookieUtil.get("data", "name")); //"Nicholas"
    alert(SubCookieUtil.get("data", "book")); //"Professional JavaScript"

    4、  IE用户数据

    1)   使用 CSS 在某个元素上指定 userData 行为,就可以使用setAttribute()方法来保存数据:

    <div style="behavior:url(#default#userData)" id="dataStore"></div>
    
    var dataStore = document.getElementById("dataStore");
    dataStore.setAttribute("name", "Nicholas");
    dataStore.setAttribute("book", "Professional JavaScript");
    dataStore.save("BookInfo");

    2)   下一次载入时,可以使用load()来获取数据:

    dataStore.load("BookInfo");
    
    dataStore.getAttribute("name")

    3)   removeAttribute()方法明确指定要删除某元素数据,只要指定属性名称。删除之后,必须像下面这样再次调用 save()来提交更改。

    dataStore.removeAttribute("name");
    
    dataStore.save("BookInfo");

    5、  Web存储机制:

    1)   storage类型(只存储字符串):

    (1)  clear(),删除所有值; Firefox 中没有实现

    (2)  getItem(name) 可以直接调用

    (3)  key(index) 获得 index 位置处的值的名字

    (4)  removeItem(name) 可以直接调用

    (5)  setItem(name,value) 可以直接调用

    (6)  length值对数量,无法判断对象中所有数据的大小,不过 IE8 提供了一个 remainingSpace 属性,用于获取还可以使用的存储空间的字节数

    2)   sessionStorage 对象

    (1)  存储方法:

    (1st)     使用方法存储数据

    sessionStorage.setItem("name", "Nicholas");

    (2nd)     使用属性存储数据

       sessionStorage.book = "Professional JavaScript";

    PS:只适用于IE8:

    sessionStorage.begin();
    sessionStorage.name = "Nicholas";
    sessionStorage.book = "Professional JavaScript";
    sessionStorage.commit();

    (2)  读取数据:

    (1st)     使用方法存储数据

    var name = sessionStorage.getItem("name");

    (2nd)     使用属性存储数据

       var book = sessionStorage.book;

    结合 length 属性和 key()方法来迭代 sessionStorage 中的值:

    for (var i=0, len = sessionStorage.length; i < len; i++){
    var key = sessionStorage.key(i);
    var value = sessionStorage.getItem(key);
    
     }

    (3)  使用 for-in 循环来迭代 sessionStorage 中的值:

    for (var key in sessionStorage){
    var value = sessionStorage.getItem(key);
    alert(key + "=" + value);
    }

    (4)  删除数据

    (1st)     使用 delete 删除一个值——在 WebKit 中无效

    delete sessionStorage.name;

    (2nd)     使用方法删除一个值

    sessionStorage.removeItem("book");

    3)   globalStorage 对象:

    //保存数据
    globalStorage["wrox.com"].name = "Nicholas";
    //获取数据
    var name = globalStorage["wrox.com"].name;

    PS: 事先不能确定域名,那么使用 location.host 作为属性名比较安全

    4)   localStorage 对象:

    //使用方法存储数据
    localStorage.setItem("name", "Nicholas");
    //使用属性存储数据
    localStorage.book = "Professional JavaScript";
    //使用方法读取数据
    var name = localStorage.getItem("name");
    //使用属性读取数据
    var book = localStorage.book;

    5)   为了兼容只支持 globalStorage 的浏览器:

    function getLocalStorage(){
    if (typeof localStorage == "object"){
    return localStorage;
    } else if (typeof globalStorage == "object"){
    return globalStorage[location.host];
    } else {
    throw new Error("Local storage not available.");
    }
    }

    使用:var storage = getLocalStorage();

    6)   storage 事件:

    (1)  属性【IE8 和 Firefox 只实现了 domain 属性】:

    domain:发生变化的存储空间的域名;

    key:设置或者删除的键名;

    newValue:如果是设置值,则是新值;如果是删除键,则是 null;

    • oldValue:键被更改之前的值;

    (2)  侦听 storage 事件:

    EventUtil.addHandler(document, "storage", function(event){
    alert("Storage changed for " + event.domain);
    });

    6、  IndexedDB(数据库,使用对象保存数据)

    1)   每一次 IndexedDB 操作,都需要注册 onerror 或 onsuccess 事件处理程序,以确保适当地处理结果

    var request, database,errorInfo;
    
    if (database.version != "1.0"){
    request = database.setVersion("1.0");
    request.onerror = function(event){
    errorInfo =  event.target.errorCode;//错误信息
    };
    request.onsuccess = function(event){
    database = event.target.result;//数据库实例对象
    };
    } else {
    alert("Database already initialized. Database name: " + database.name +
    ", Version: " + database.version);
    }

    第二十四章

    1、  可维护性

    2、  解耦

        

  • 相关阅读:
    谷歌插件开发(实现CSDN快速登陆)
    uva216 c++回溯法
    基于Linux的owncloud搭建
    Android常用代码集合
    详谈 php定时器
    Codeforces 278C Learning Languages(并查集)
    WPF中的快捷键(累积中)
    学从难出学,用从易处用
    面向对象的一种简单理解(贴标签)
    WPF与Winform中的不同(1)
  • 原文地址:https://www.cnblogs.com/qzccl/p/5320938.html
Copyright © 2011-2022 走看看