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();
 };
等待页面加载完毕后再执行函数的方法:
 

猜你喜欢

转载自www.cnblogs.com/luckyboylch/p/12330216.html
今日推荐