可以利用HTML DOM为dom元素创建属性:elem.myAttr = value;
onclick回调函数是无参函数,要想传参可以在dom元素中添加自定义属性,然后再在回调函数中获取该属性.
parseInt()函数可以将以数字开头的字符串前面的数字提取出来.
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:
环境;在 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语法。
法,因为这样可能会导致意外。我们建议在初始化变量之前,一定要先声明,这样就
可以避免类似问题。在严格模式下,初始化未经声明的变量会导致错误。因此建议先利用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声明和初始化的变量,直接初始化不声明的变量在全局作用域中),都可以认为是私有变量,因为不能在函数的外部访问这些变量。私有变量包括函数的参数、局部变量和在函数内部定义的其他函数。但通过特权方法可以访问函数中定义的私有变量和私有方法。
任何在函数中定义的变量(以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()方法,可以
从相反的方向来模拟队列,即在数组的前端添加项,从数组末端移除项
它能在数组前端添加任意个项并返回新数组的长度。因此,同时使用 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()方法先后推入了 3 个值。首先是"red"和"green",然
后是"black",数组中各项的顺序为"black"、 "red"、 "green"。在调用 pop()方法时,移除并返回
的是最后一项,即"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()则会对它发现的任何非标准字符进行编码。来看下面的例子。
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()的原因所在。
对整个 URI 使用 encodeURI(),而只能对附加在现有 URI 后面的字符串使用 encodeURIComponent()的原因所在。
一 般 来 说 , 我 们 使 用 encodeURIComponent() 方 法 的 时 候 要 比 使 用encodeURI()更多,因为在实践中更常见的是对查询字符串参数而不是对基础 URI进行编码。
与 encodeURI()和 encodeURIComponent()方法对应的两个方法分别是 decodeURI()和decodeURIComponent()。其中, decodeURI()只能对使用 encodeURI()替换的字符进行解码。例如,
它可将%20 替换成一个空格,但不会对%23 作任何处理,因为%23 表示井字号( #),而井字号不是使用encodeURI()替换的。同样地, decodeURIComponent()能够解码使用 encodeURIComponent()编码
的所有字符,即它可以解码任何特殊字符的编码。来看下面的例子:
与 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对象的属性。
所有特殊字符的编码都被替换成了原来的字符,得到了一个未经转义的字符串(但这个字符串并不是一个有效的 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)。这一做法适用于大多数全局变量和全局对象的属性。局部变量会在它们离开执行环境时自动被解除引用。不过,解除一个值的引用并不意味着自动回收该值所占用的内存。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。
做法叫做解除引用( 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;
鼠标在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(); };
等待页面加载完毕后再执行函数的方法: