• JavaScript-笔记2


    可以利用HTML DOM为dom元素创建属性:elem.myAttr = value;
    onclick回调函数是无参函数,要想传参可以在dom元素中添加自定义属性,然后再在回调函数中获取该属性.
     
    parseInt()函数可以将以数字开头的字符串前面的数字提取出来.
     
    js文件间若存在依赖关系,需要先加载依赖的js,然后就可在其他js中使用其中定义的函数和变量.
     
    变量初始化:
    JS中没有块级作用域
    例1:
    for (var i=0; i < 10; i++){
        doSomething(i);
    }
    alert(i); //10
    例2:
    if (true) {
        var color = "blue";
    }
    alert(color); //"blue"
        使用 var 声明的变量会自动被添加到最接近的环境中。在函数内部,最接近的环境就是函数的局部
    环境;在 with 语句中,最接近的环境是函数环境。如果初始化变量时没有使用 var 声明,该变量会自
    动被添加到全局环境。
    例3:
    function add(num1, num2) {
        sum = num1 + num2;
        return sum;
    }
    var result = add(10, 20); //30
    alert(sum); //30
        在编写 JavaScript 代码的过程中,不声明而直接初始化变量是一个常见的错误做
    法,因为这样可能会导致意外。我们建议在初始化变量之前,一定要先声明,这样就
    可以避免类似问题。在严格模式下,初始化未经声明的变量会导致错误。因此建议先利用var 声明,再初始化使用.
    注:严格模式即"use strict";   放置到脚本开头或函数开头,以表示当前范围需要严格要求js语法。
     
    但可以利用匿名函数实现块级作用域:
    函数表达式:将函数声明包含在一对圆括号中
    (function(){
        //这里是块级作用域
    })();
    function(){        //这段代码会导致语法错误,是因为 JavaScript 将 function 关键字当作一个函数声明的开始,而函数声明后面不能跟圆括号。然而,函数表达式的后面可以跟圆括号。
        //这里是块级作用域
    }(); //出错!
    var myFunc = function(){};    或    var result = function(){}();        也是函数表达式
    私有作用域例子:
    function outputNumbers(count){
    (function () {
    for (var i=0; i < count; i++){
    alert(i);
    }
    })();
    alert(i); //导致一个错误!
    }
    而通过创建私有作用域,每个开发人员既可以使用自己的变量,又不必担心搞乱全局作用域。
    这种做法可以减少闭包占用的内存问题,因为没有指向匿名函数的引用。只要函数执行完毕,就可以立即销毁其作用域链了。

        任何在函数中定义的变量(以var声明和初始化的变量,直接初始化不声明的变量在全局作用域中),都可以认为是私有变量,因为不能在函数的外部访问这些变量。私有变量包括函数的参数、局部变量和在函数内部定义的其他函数。但通过特权方法可以访问函数中定义的私有变量和私有方法。
        当在函数内部定义了其他函数时,就创建了闭包。闭包有权访问包含函数内部的所有变量 。通常,函数的作用域及其所有变量都会在函数执行结束后被销毁。 但是,当函数返回了一个闭包时,这个函数的作用域将会一直在内存中保存到闭包不存在为止。 
    单例模式、所有实例共享私有变量和私有函数的静态私有变量方法详见《JS高级程序设计》P204
    function MyObject(){    //构造函数
    //私有变量和私有函数(均无法在外部访问)
    var privateVariable = 10;
    function privateFunction(){
        return false;
    }
    //特权方法作为闭包有权访问私有变量和私有函数
    this.publicMethod = function (){
    privateVariable++;
    return privateFunction();
    };
    }
    用私有和特权成员,可以隐藏那些不应该被直接修改的数据,例如:
    function Person(name){
    this.getName = function(){
        return name;
    };
    this.setName = function (value) {
        name = value;
    };
    }
    var person = new Person("Nicholas");
    alert(person.getName()); //"Nicholas"
    person.setName("Greg");
    alert(person.getName()); //"Greg"
    注:构造函数模式的缺点是针对每个实例都会创建同样一组新方法 。
     
    JavaScript 从来不会告诉你是否多次声明了同一个变量;遇到这种情况,它只会对后续的声明视而不见(不过,它会执行后续声明中的变量初始化)。

    JS中对于基本类型的赋值操作,属于深拷贝(基本类型变量保存在栈中);对于object对象的赋值操作,拷贝的是指针,拷贝前后指向同一对象(引用变量保存在栈中,但引用所指向的对象保存在堆中)
     
    Object类型:
            虽然 Object 的实例不具备多少功能,但对于在应用程序中存储和传输数据而言,它们确实是非常理想的选择。
    创建object实例的方式有两种:
    方式1:使用new操作符后跟object构造函数
    var person = new Object();    // 或 var person = {};
    person.name = "Nicholas";
    person.age = 29;
    方式2:使用对象字面量表示法    - 推荐
    var person = {
    name : "Nicholas",
    age : 29
    };
    在使用对象字面量语法时,属性名也可以使用字符串 :
    var person = {
    "name" : "Nicholas",
    "age" : 29,
    5 : true
    };
    虽然可以使用前面介绍的任何一种方法来定义对象,但开发人员更青睐对象字面量语法,因为这种
    语法要求的代码量少,而且能够给人封装数据的感觉。实际上,对象字面量也是向函数传递大量可选参
    数的首选方式。
    访问oject对象属性的方法:
    alert(person["name"]);     //"Nicholas"
    alert(person.name);         //"Nicholas"    推荐
     
    Array类型:
            但与其他语言不同的是, ECMAScript 数组的每一项可以保存任何类型的数据。也就是说,可以用数组的第一个位置来保存字符串,用第二位置来保存数值,用第三个位置来保存对象,
    以此类推。而且, ECMAScript 数组的大小是可以动态调整的,即可以随着数据的添加自动增长以容纳新增数据。
    创建数组的两种方式:
    方式1:使用Array构造函数
    var colors = new Array(); 
    var colors = new Array(20); 
    var colors = new Array("red", "blue", "green"); 
    var colors = Array(3);     //也可省略new,这意味着自定义的构造函数只需像普通函数那样定义,用this指定属性,然后像普通函数那样使用即可创建实例。
     方式2:数组字面量表示法
    var colors = ["red", "blue", "green"];
    var names = [];
    数组的 length 属性很有特点——它不是只读的。因此,通过设置这个属性,可以从数组的末尾移除项或向数组中添加新项。
    var colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
    colors.length = 2;
    alert(colors[2]); //undefined 
    如果将其 length 属性设置为大于数组项数的值,则新增的每一项都会取得 undefined 值:
    var colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
    colors.length = 4;
    alert(colors[3]); //undefined
    操作数组:
    var colors = ["red", "blue", "green"]; // 定义一个字符串数组
    alert(colors[0]); // 显示第一项
    colors[2] = "black"; // 修改第三项
    colors[3] = "brown"; // 新增第四项
    检测数组:
    方法1:
    if (value instanceof Array){
    //对数组执行某些操作
    } 
    方法2:    推荐
    if (Array.isArray(value)){
    //对数组执行某些操作
    }
    转换方法:
    var colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
    alert(colors.toString()); // red,blue,green    默认返回以逗号拼接的字符串
    alert(colors.valueOf()); // red,blue,green    返回的还是数组
    alert(colors); // red,blue,green
    var person1 = {
    toLocaleString : function () {    //toLocalString默认与toString输出相同
    return "Nikolaos";
    },
    toString : function() {    //重写toString函数
    return "Nicholas";
    }
    };
    var person2 = {
    toLocaleString : function () {
    return "Grigorios";
    },
    toString : function() {
    return "Greg";
    }
    };
    var people = [person1, person2];
    alert(people); //Nicholas,Greg
    alert(people.toString()); //Nicholas,Greg
    alert(people.toLocaleString()); //Nikolaos,Grigorios
    也可利用Join手工构建返回的数组字符串:
       var colors = ["red", "green", "blue"];
    alert(colors.join(",")); //red,green,blue
    alert(colors.join("||")); //red||green||blue
    注:如果数组中的某一项的值是 null 或者 undefined,那么该值在 join()、toLocaleString()、 toString()和 valueOf()方法返回的结果中以空字符串表示。
    栈方法:让数组变得像栈的方法(LIFO后进先出)
    var colors = ["red", "blue"];
    colors.push("brown"); // 添加另一项
    colors[3] = "black"; // 添加一项
    alert(colors.length); // 4
    var item = colors.pop(); // 取得最后一项
    alert(item); //"black"
    队列方法:让数组变得像队列的方法(FIFO先进先出)
    var colors = new Array(); //创建一个数组
    var count = colors.push("red", "green"); //推入两项
    alert(count); //2
    count = colors.push("black"); //推入另一项
    alert(count); //3
    var item = colors.shift(); //取得第一项
    alert(item); //"red"
    alert(colors.length); //2 
        ECMAScript 还为数组提供了一个 unshift()方法。顾名思义, unshift()与 shift()的用途相反:
    它能在数组前端添加任意个项并返回新数组的长度。因此,同时使用 unshift()和 pop()方法,可以
    从相反的方向来模拟队列,即在数组的前端添加项,从数组末端移除项
    var colors = new Array(); //创建一个数组
    var count = colors.unshift("red", "green"); //推入两项,按顺序在前面插入,即数组顺序为red, green
    alert(count); //2 
    count = colors.unshift("black"); //推入另一项
    alert(count); //3
    var item = colors.pop(); //取得最后一项
    alert(item); //"green"
    alert(colors.length); //2
        这个例子创建了一个数组并使用 unshift()方法先后推入了 个值。首先是"red""green",然
    后是"black",数组中各项的顺序为"black"、 "red"、 "green"。在调用 pop()方法时,移除并返回
    的是最后一项,即"green"
    重排序方法:
    反转数组顺序:
    var values = [1, 2, 3, 4, 5];
    values.reverse();
    alert(values); //5,4,3,2,1
    sort方法默认按从小到大排序,会调用数组每项的toString方法转成字符串来比较,这会导致在比较数字时出现问题:
    var values = [0, 1, 5, 10, 15];
    values.sort();
    alert(values); //0,1,10,15,5
    自定义比较函数:
    function compare(value1, value2) {
    if (value1 < value2) {
        return -1;
    } else if (value1 > value2) {
        return 1;
    } else {
        return 0;
    }
    } 
    或:
    function compare(value1, value2){
        return value2 - value1;
    }
    var values = [0, 1, 5, 10, 15];
    values.sort(compare);
    alert(values); //0,1,5,10,15
    操作方法:
    数组拼接:
    var colors = ["red", "green", "blue"];
    var colors2 = colors.concat("yellow", ["black", "brown"]);
    alert(colors); //red,green,blue    创建新数组,不影响源数组
    alert(colors2); //red,green,blue,yellow,black,brown
    数组切片:    如果 slice()方法的参数中有一个负数,则用数组长度加上该数来确定相应的位置。
    var colors = ["red", "green", "blue", "yellow", "purple"];
    var colors2 = colors.slice(1);
    var colors3 = colors.slice(1,4);
    alert(colors2); //green,blue,yellow,purple
    alert(colors3); //green,blue,yellow    创建新数组,不影响源数组
    功能最强大方法:splice()
    splice()的主要用途是向数组的中部插入项,但使用这种方法的方式则有如下 3 种。
     删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。
        例如,
        例如, splice(0,2)会删除数组中的前两项。
     插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、 0(要删除的项数)
    和要插入的项。如果要插入多个项,可以再传入第四、第五,以至任意多个项。例如,
    splice(2,0,"red","green")会从当前数组的位置 2 开始插入字符串"red"和"green"。
     替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起
    始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例如,
    splice (2,1,"red","green")会删除当前数组位置 2 的项,然后再从位置 2 开始插入字符串
    "red"和"green"。
    splice()方法始终都会返回一个数组,该数组中包含从原始数组中删除的项(如果没有删除任何
    项,则返回一个空数组)。
    项,则返回一个空数组)。
    位置方法:
            ECMAScript 5 为数组实例添加了两个位置方法: indexOf()和 lastIndexOf()。这两个方法都接收
    两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中,
    两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, indexOf()方法从数组的开头(位
    置置 0)开始向后查找, lastIndexOf()方法则从数组的末尾开始向前查找。
    这两个方法都返回要查找的项在数组中的位置,或者在没找到的情况下返回
    这两个方法都返回要查找的项在数组中的位置,或者在没找到的情况下返回1。在比较第一个参数
    与数组中的每一项时,会使用全等操作符;也就是说,要求查找的项必须严格相等(就像使用
    与数组中的每一项时,会使用全等操作符;也就是说,要求查找的项必须严格相等(就像使用===一样)。
    迭代方法:
    ECMAScript 5 为数组定义了 5 个迭代方法。每个方法都接收两个参数:要在每一项上运行的函数和
    (可选的)运行该函数的作用域对象——影响 this 的值。传入这些方法中的函数会接收三个参数:数
    组项的值、该项在数组中的位置和数组对象本身。根据使用的方法不同,这个函数执行后的返回值可能
    会也可能不会影响方法的返回值。以下是这 5 个迭代方法的作用。
     every():对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true。(与运算)
     filter():对数组中的每一项运行给定函数,返回该函数会返回 true 的项组成的数组。(条件过滤)
     forEach():对数组中的每一项运行给定函数。这个方法没有返回值。(对每项执行相同操作,无返回值)
     map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。(对每项执行相同操作,有返回值)
     some():对数组中的每一项运行给定函数,如果该函数对任一项返回 true,则返回 true。(或运算)
    以上方法都不会修改数组中的包含的值。
    var numbers = [1,2,3,4,5,4,3,2,1];
    var everyResult = numbers.every(function(item, index, array){
    return (item > 2);
    });
    alert(everyResult); //false
    var someResult = numbers.some(function(item, index, array){
    return (item > 2);
    });
    alert(someResult); //true
    var mapResult = numbers.map(function(item, index, array){
    return item * 2;
    });
    alert(mapResult); //[2,4,6,8,10,8,6,4,2]
    numbers.forEach(function(item, index, array){
    //执行某些操作
    });
    归并方法:使用 reduce()还是 reduceRight(),主要取决于要从哪头开始遍历数组。除此之外,它们完全相同。
    使用 reduce()方法可以执行求数组中所有值之和的操作,比如:
    var values = [1,2,3,4,5];
    var sum = values.reduce(function(prev, cur, index, array){
    return prev + cur;
    });
    alert(sum); //15
     
    Function类型:
    JS中不存在函数重载的概念,因为函数名只是指向函数对象的指针。因此后定义的函数会覆盖前面定义的函数.
    function sum (num1, num2) {
    return num1 + num2;
    }
    ====>  等价于(除了什么时候可以通过变量访问函数这一点区别之外,函数声明与函数表达式的语法其实是等价的。 函数声明有提升,当变量初始化无提升)
    var sum = function(num1, num2){
    return num1 + num2;
    };
    每个函数都是 Function 类型的实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。
    一个函数可以有多个名字。
    function sum(num1, num2){
    return num1 + num2;
    }
    alert(sum(10,10)); //20
    var anotherSum = sum;
    alert(anotherSum(10,10)); //20
    sum = null;
    alert(anotherSum(10,10)); //20
    函数内部属性this:
    在函数内部,有两个特殊的对象: arguments 和 this。 arguments主要是保存函数参数的作用。
    this引用的是函数据以执行的环境对象——或者也可以说是 this 值(当在网页的全局作用域中调用函数时,this 对象引用的就是 window)。
    window.color = "red";
    var o = { color: "blue" };
    function sayColor(){
    alert(this.color);
    }
    sayColor(); //"red"
    o.sayColor = sayColor;
    o.sayColor(); //"blue"
        上面这个函数 sayColor()是在全局作用域中定义的,它引用了 this 对象。由于在调用函数之前,
    this 的值并不确定,因此 this 可能会在代码执行过程中引用不同的对象。当在全局作用域中调用
    sayColor()时, this 引用的是全局对象 window;换句话说,对 this.color 求值会转换成对
    window.color 求值,于是结果就返回了"red"。而当把这个函数赋给对象 o 并调用 o.sayColor()
    时, this 引用的是对象 o, 因此对 this.color 求值会转换成对 o.color 求值,结果就返回了"blue"。
    注:函数的名字仅仅是一个包含指针的变量而已。因此,即使是在不同的环境中执行,全局的 sayColor()函数与 o.sayColor()指向的仍然是同一个函数。
     
    在全局函数中, this 等于 window,而当函数被作为某个对象的方法调用时, this 等于那个对象。不过,匿名函数的执行环境具有全局性,因此其 this 对象通常指向 window。
    var name = "The Window";
    var object = {
    name : "My Object",
    getNameFunc : function(){
    return function(){
        return this.name;
    };
    }
    };
    alert(object.getNameFunc()()); //"The Window"(在非严格模式下)
     
    函数内部属性func.inner:
        这个属性中保存着调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,它的值为 null。
    length 属性:表示函数希望接收的命名参数的个数
    function sayName(name){
    alert(name);
    }
    function sum(num1, num2){
    return num1 + num2;
    }
    function sayHi(){
    alert("hi");
    }
    alert(sayName.length); //1
    alert(sum.length); //2
    alert(sayHi.length); //0
    apply()和call()方法:
        每个函数都包含两个非继承而来的方法: apply()和 call()。这两个方法的用途都是在特定的作
    用域中调用函数,实际上等于设置函数体内 this 对象的值。首先, apply()方法接收两个参数:一个
    是在其中运行函数的作用域,另一个是参数数组。其中,第二个参数可以是 Array 的实例,也可以是
    arguments 对象。 
    function sum(num1, num2){
        return num1 + num2;
    }
    function callSum1(num1, num2){
        return sum.apply(this, arguments); // 传入 arguments 对象
    }
    function callSum2(num1, num2){
        return sum.apply(this, [num1, num2]); // 传入数组
    }
    alert(callSum1(10,10)); //20
    alert(callSum2(10,10)); //20
     
        call()方法与 apply()方法的作用相同,它们的区别仅在于接收参数的方式不同。对于 call()方法而言,第一个参数是 this 值没有变化,变化的是其余参数都直接传递给函数。换句话说,在使用
    call()方法时,传递给函数的参数必须逐个列举出来。在使用 call()方法的情况下, callSum()必须明确地传入每一个参数。结果与使用 apply()没有什么不同。至于是使用 apply()还是 call(),完全取决于你采取哪种给函数传递参数的方式最方便。如果你打算直接传入 arguments 对象,或者包含函数中先接收到的也是一个数组,那么使用 apply()肯定更方便;否则,选择 call()可能更合适。(在不给函数传递参数的情况下,使用哪个方法都无所谓。)
        事实上,传递参数并非 apply()和 call()真正的用武之地;它们真正强大的地方是能够扩充函数赖以运行的作用域。
        使用 call()(或 apply())来扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系。 
    window.color = "red";
    var o = { color: "blue" };
    function sayColor(){
        alert(this.color);
    }
    sayColor(); //red
    sayColor.call(this); //red
    sayColor.call(window); //red
    sayColor.call(o); //blue
    bind()方法:这个方法会创建一个函数的实例,其 this 值会被绑定到传给 bind()函数的值。例如:
    window.color = "red";
     
    var o = { color: "blue" };
     
    function sayColor(){
     
    alert(this.color);
     
    }
     
    var objectSayColor = sayColor.bind(o);    //将sayColor的函数别名绑定到o作用域对象.
     
    objectSayColor(); //blue
    字符串匹配(正则匹配)及常用方法:见《JavaScript高级程序设计P140》
     
    Global全局对象:
    1. URI 编码方法
    Global 对象的 encodeURI()和 encodeURIComponent()方法可以对 URI( Uniform Resource
    Identifiers,通用资源标识符)进行编码,以便发送给浏览器。有效的 URI 中不能包含某些字符,例如
    空格。而这两个 URI 编码方法就可以对 URI 进行编码,它们用特殊的 UTF-8 编码替换所有无效的字符,
    从而让浏览器能够接受和理解。
    其中, encodeURI()主要用于整个 URI(例如, http://www.wrox.com/illegal value.htm),而 encodeURIComponent()主要用于对 URI 中的某一段(例如前面 URI 中的 illegal value.htm)进行编码。
    它们的主要区别在于, encodeURI()不会对本身属于 URI 的特殊字符进行编码,例如冒号、正斜杠、
    问号和井字号;而 encodeURIComponent()则会对它发现的任何非标准字符进行编码。来看下面的例子。
    var uri = "http://www.wrox.com/illegal value.htm#start";
    //"http://www.wrox.com/illegal%20value.htm#start"
    alert(encodeURI(uri));
    //"http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start"
    alert(encodeURIComponent(uri));
            使用 encodeURI()编码后的结果是除了空格之外的其他字符都原封不动,只有空格被替换成了%20。而 encodeURIComponent()方法则会使用对应的编码替换所有非字母数字字符。这也正是可以
    对整个 URI 使用 encodeURI(),而只能对附加在现有 URI 后面的字符串使用 encodeURIComponent()的原因所在。
            一 般 来 说 , 我 们 使 用 encodeURIComponent() 方 法 的 时 候 要 比 使 用encodeURI()更多,因为在实践中更常见的是对查询字符串参数而不是对基础 URI进行编码。
            与 encodeURI()和 encodeURIComponent()方法对应的两个方法分别是 decodeURI()decodeURIComponent()。其中, decodeURI()只能对使用 encodeURI()替换的字符进行解码。例如,
    它可将%20 替换成一个空格,但不会对%23 作任何处理,因为%23 表示井字号( #),而井字号不是使用encodeURI()替换的。同样地, decodeURIComponent()能够解码使用 encodeURIComponent()编码
    的所有字符,即它可以解码任何特殊字符的编码。来看下面的例子:
    var uri = "http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start";
    //http%3A%2F%2Fwww.wrox.com%2Fillegal value.htm%23start
    alert(decodeURI(uri));
    //http://www.wrox.com/illegal value.htm#start
    alert(decodeURIComponent(uri)); 
            这里, 变量 uri 包含着一个由 encodeURIComponent()编码的字符串。在第一次调用 decodeURI()输出的结果中,只有%20 被替换成了空格。而在第二次调用 decodeURIComponent()输出的结果中,
    所有特殊字符的编码都被替换成了原来的字符,得到了一个未经转义的字符串(但这个字符串并不是一个有效的 URI)。


    在全局作用域中声明的所有变量和函数,就都成为了 window对象的属性。
    var color = "red";
    function sayColor(){
        alert(window.color);
    }
    window.sayColor(); //"red"
     
    字典的使用:
    js中数组排序[].sort()是按字符串的字典序来排的,对数字数组无效:
     
    js在比较数字时,不允许有连续多个比较符(eg: 206<0<234),这样结果会将前面的false或true转成0/1再继续比较. 应借助&&、||来实现.
     
    判断是否为null: 
    var === null
    判断是否为undefined: 
    typeof(exp) == "undefined"
     
    字符串的全局替换:
    var str = ' hello workd haha';
    var res = str.replace(/s+/g, '')
     
    从数组中删除某个指定的元素:
     
    获取对象中元素的个数:(字典)
    var aa = {'a': 1, 'b': 2}
    console.log(Object.getOwnPropertyNames(aa).length)    或 Object.keys(aa).length
    注意对象没有length属性.
     
    js生成某个范围的随机整数:
     
    js根据类名className或tagName删除元素:(for循环删除有坑)
                var entityGroupEle = entityRectEle.parentNode;
                var badEntityPaths = entityGroupEle.getElementsByTagName('path');
                while (badEntityPaths.length > 0) {
                    entityGroupEle.removeChild(badEntityPaths[0]);
                    badEntityPaths = entityGroupEle.getElementsByTagName('path');
                }    
    ========================            项目中一些实用的函数:            =================================
    //添加文档加载完要执行的函数
    function addLoadEvent(func){
        var oldonload = window.onload;
        if(typeof window.onload != 'function'){
            window.onload = func;
        } else {
            window.onload = function(){
                oldonload();
                func();
            }
        }
    }
     
    //在某个dom元素后插入新元素
    function insertAfter(newElement, targetElement){
        var parent = targetElement.parentNode;
        if(parent.lastChild == targetElement){
            parent.appendChild(newElement);
        } else {
            parent.insertBefore(newElement, targetElement.nextSibling);
        }
    }
     
    //为某个dom元素添加css类
    function addClass(element, value){
        if(!element.className){ //若未定义class属性
            element.className = value;
        } else{ //在已有css上添加新样式
            newClassName = element.className;
            newClassName += " ";
            newClassName += value;
            element.className = newClassName;
        }
    }
     
    ==============================        web项目开发经验        ===========================
    千万不要完全依赖 JavaScript。客户端验证并不能取代服务器端的验证。即使有了JavaScript 验证,服务器端照样还应该对接收到 的数据再次验证。
     
    客户端验证的目的在于帮助用户填好表单,避免他们提交未完成的表单,从而节省他们的时间。服务器端验证的目的在于保护数据库和后台系统的安全。
     
    为减少对图片的请求次数,可以把多张图片拼接成单张图像,然后获取其中部分.
     
    代码压缩工具:Closure Compiler ;提倡在项目发布时将所有js文件整合到一个js文件中并进行压缩,以提升网站性能.
     
    确保占用最少的内存可以让页面获得更好的性能。而优化内存占用的最佳方式,就是为执行中的代码只保存必要的数据。一旦数据不再有用,最好通过将其值设置为 null 来释放其引用——这个
    做法叫做解除引用( dereferencing)。这一做法适用于大多数全局变量和全局对象的属性。局部变量会在它们离开执行环境时自动被解除引用。不过,解除一个值的引用并不意味着自动回收该值所占用的内存。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。

    获取DOM元素的尺寸和位置:
     
    DOM元素的插入:
    将dom元素A插入到父元素为B的dom元素C前面:
    B.insertBefore(A, C); //A为新插入元素,C为参照元素, B为新插入元素的父元素.  当C为null时,表示将A插入到B的最后.
    获取某个dom元素下面的tagName子元素:
    element.getElementsByTagName("tagName")
     
    添加和移除监听事件:
     
    添加和移除window resize监听事件:
    方法1:
    window.addEventListener('resize', resizeRender, false);
    window.removeEventListener('resize', resizeRender, false);
    方法2:
    window.onresize = resize;
    window.onresize = null;
    方法3:
    $(window).on('resize', resize);
    $(window).unbind('resize', resize);
    方法4:
    $(window).resize(function () {});
     
    触发鼠标双击事件而不触发鼠标单击事件:
    https://www.hangge.com/blog/cache/detail_1794.html(该法对于jQuery通过on绑定的事件有点不正常)
     
    计算鼠标在某个元素内部的相对位置:https://www.iteye.com/blog/747017186-2048303
    获取鼠标在整个页面的位置:
    var pagex = event.pageX || scroll().left + event.clientX;  
    var pagey = event.pageY || scroll().top + event.clientY;  
    控制滚动条的位置:https://www.jianshu.com/p/c4473018807c
     
    鼠标在div内移动时,div的滚动条自动跟随鼠标滚动:
    var onMouseMove = function(evt){
                         var svgDivBox = $('.unlabel-text-svg-box')[0];
                        var dy = evt.pageY - $(svgDivBox).offset().top;
                        var dyPercentage = dy / svgDivBox.clientHeight;
                        // svgDivBox.scrollTop = dyPercentage * svgDivBox.scrollHeight    //与下者等价
                        svgDivBox.scrollTo(0, dyPercentage * svgDivBox.scrollHeight);
    }
     
    事件event对象中的坐标:https://www.jianshu.com/p/a52077e8369d
     
    js获取浏览器窗口不包含滚动条可拖动宽度:
    window.innerWidth(document.body.clientWidth还是包含)
     
    document.oncontextmenu = function(){return false;}    //整个页面的默认右击事件均失效
    $(document).bind("contextmenu",function(e){
              return false;
        });
    推荐:
    document.getElementsByClassName('ti-modal ti-fade ti-in')[0].oncontextmenu = function (e) {
                            e.preventDefault();
     };
    等待页面加载完毕后再执行函数的方法:
     
  • 相关阅读:
    PHP生成二维码并上传到七牛云
    算法入门---选择排序
    算法入门
    react入门-refs
    react入门-props.children
    react入门-组件方法、数据和生命周期
    react入门-jsx
    递归
    node的path.join 和 path.resolve的区别
    vuex的使用
  • 原文地址:https://www.cnblogs.com/luckyboylch/p/12330216.html
Copyright © 2020-2023  润新知