javascript学习
//1.undefined 是派生自null的 //alert(undefined == null); //alert(undefined === null); ////结果 true false //2.建议还是养成编码的规范, //不要忘记初始化变量。 //var box; //var car = null; //alert(typeof box == typeof car) //结果false //var hello = 'Hello World!'; //var hello2 = Boolean(hello); //alert(typeof hello); ////String类型 //上面是一种显示转换,属于强制性转换。 //而实际应用中,还有一种隐式转换。 //比如,在if 条件语句里面的条件判断,就存在隐式转换。 //var hello = 'Hello World!'; //if (hello) { // alert('如果条件为true,就执行我这条!');//结果:true //} else { // alert('如果条件为false,就执行我这条!'); //} //以下是其他类型转换成Boolean类型规则 //数据类型转换为true 的值转换为false 的值 //Boolean true false //String 任何非空字符串空字符串 //Number 任何非零数字值(包括无穷大) 0 和NaN //Object 任何对象null //Undefined undefined //要想确定一个数值到底是否超过了规定范围, //可以使用isFinite()函数。如果没有超过, //返回true,超过了返回false。 //可以通过Number.NaN 得到NaN 值, //任何与NaN 进行运算的结果均为NaN, //NaN 与自身不相等(NaN 不与任何值相等)。 //alert(Number.NaN); //NaN //alert(NaN+1); //NaN //alert(NaN == NaN) //false //继承 //function Box() { // this.name = '测试'; // this.age = 18; // this.height = 171; //} //function Test() { // this.sex = '男'; //} //Test.prototype = new Box(); //var test = new Test(); //alert(test.age); //function Box(name, age) { // alert("姓名:" + name + "年龄:" + age); //} //Box("asd", 12); //function Box(name,age) //{ // return '你的姓名:' + name + ',年龄' + age; //} //alert(Box('测试', 18)); //function Box(num1,num2) { // return num1 * num2; //} //var num = Box(15, 15); //alert(num); //function Box(num) { // if (num < 50) { // return num; // } // else { // return 100; // } //} //alert(Box(10)); //alert(Box(80)); //function Box() { // return arguments[0] + '|' + arguments[1];//得到每次参数的值 //} //alert(Box(1, 2, 3, 4, 5, 6));//传递参数 //function Box() { // return arguments.length;//得到6 //} //alert(Box(1, 2, 3, 4, 56, 7)); //function box() { // var sum = 0; // if (arguments.length == 0) { // return sum;//如果没有参数就返回0; // } // for (var i = 0; i < arguments.length; i++) {//如果有,则累加 // sum = sum + arguments[i]; // } // return sum;//返回累加结果 //} //alert(box(2, 6541, 3, 1)); //var box = new Object(); //box.name='测试name'; //box.age = 28; //alert(box['name']) //alert(box['age']) //delete box.age;//删除属性 //alert(box['name']) //alert(box.age)//undefined // var box = [ //{ //第一个元素是一个对象 // name: '李炎恢', // age: 28, // run: function () { // return 'run 了'; // } //}, //['马云', '李彦宏', new Object()],//第二个元素是数组 //'江苏', //第三个元素是字符串 //25 + 25, //第四个元素是数值 //new Array(1, 2, 3) //第五个元素是数组 // ]; //var box = ['李炎恢', 28, '盐城']; //当前数组 //var box2 = box.slice(1); //box.slice(1,3),2-4 之间的元素 //alert(box2); //28,盐城 //alert(box); //当前数组 //splice 中的删除功能: //var box = ['李炎恢', 28, '盐城']; //当前数组 //var box2 = box.splice(0,2); //截取前两个元素 //alert(box2); //返回截取的元素 //alert(box); //当前数组被截取的元素被删除 //splice 中的插入功能: //var box = ['李炎恢', 28, '盐城']; //当前数组 //var box2 = box.splice(1, 0, '计算机编程', '江苏'); //没有截取,但插入了两条 //alert(box2); //在第2 个位置插入两条 //alert(box); //输出 //splice 中的替换功能: //var box = ['李炎恢', 28, '盐城']; //当前数组 //var box2 = box.splice(1, 1, 100); //alert(box2); //alert(box); //Date: //var box = new Date(Date.UTC(2011, 11, 5, 15, 13, 16)); //alert('toString:' + box.toString()); //alert('toLocaleString:' + box.toLocaleString()); //按本地格式输出 //PS:这两个方法在不同浏览器显示的效果又不一样,但不用担心,这两个方法只是在 //调试比较有用,在显示时间和日期上,没什么价值。valueOf()方法显示毫秒数。 //日期格式化方法 //Date 类型还有一些专门用于将日期格式化为字符串的方法。 //var box = new Date(); //alert(box.toDateString()); //以特定的格式显示星期几、月、日和年 //alert(box.toTimeString()); //以特定的格式显示时、分、秒和时区 //alert(box.toLocaleDateString()); //以特定地区格式显示星期几、月、日和年 //alert(box.toLocaleTimeString()); //以特定地区格式显示时、分、秒和时区 //alert(box.toUTCString()); //以特定的格式显示完整的UTC 日期。 //alert(box.getTime()); //获取日期的毫秒数,和valueOf()返回一致 //alert(box.setTime(100)); //以毫秒数设置日期,会改变整个日期 //alert(box.getFullYear()); //获取四位年份 //alert(box.setFullYear(2012)); //设置四位年份,返回的是毫秒数 //alert(box.getMonth()); //获取月份,没指定月份,从0 开始算起 //alert(box.setMonth(11)); //设置月份 //alert(box.getDate()); //获取日期 //alert(box.setDate(8)); //设置日期,返回毫秒数 //alert(box.getDay()); //返回星期几,0 表示星期日,6 表示星期六 //alert(box.setDay(2)); //设置星期几 //alert(box.getHours()); //返回时 //alert(box.setHours(12)); //设置时 //alert(box.getMinutes()); //返回分钟 //alert(box.setMinutes(22)); //设置分钟 //alert(box.getSeconds()); //返回秒数 //alert(box.setSeconds(44)); //设置秒数 //alert(box.getMilliseconds()); //返回毫秒数 //alert(box.setMilliseconds()); //设置毫秒数 //alert(box.getTimezoneOffset()); //返回本地时间和UTC 时间相差的分钟数 //alert(/box/i.test('This is a Box!')); //alert(/box/i.exec('This is a Box!')); //除了test()和exec()方法,String 对象也提供了4 个使用正则表达式的方法。 //String 对象中的正则表达式方法 //方法 含义 //match(pattern) 返回pattern 中的子串或null //replace(pattern, replacement) 用replacement 替换pattern //search(pattern) 返回字符串中pattern 开始位置 //split(pattern) 返回字符串按指定pattern 拆分的数组 /*使用match 方法获取获取匹配数组*/ //var pattern = /box/ig; //var str = 'This is a Box!,That is a Box too'; //alert(str.match(pattern));//匹配到两个Box,Box //alert(str.match(pattern).length);//获取数组的长度 2 /*使用search来查找匹配数据*/ //var pattern = /box/ig; //var str = "This is a Box!,That is Box too"; //alert(str.search(pattern));//查找到返回位置,否则返回-1; //PS:因为search方法查找到即返回,也就是说无需g全局. ///*使用replace 替换匹配到的数据*/ //var pattern = /box/ig; //var str = 'This is a Box!,That is a Box too'; //alert(str.replace(pattern, 'Tom')); //将Box 替换成了Tom //var pattern = / /ig; //var str = 'This is a Box!,That is a Box too'; //alert(str.split(pattern)); //将空格拆开分组成数组 //RegExp对象的静态属性 //属性短名 含义 //input $_ 当前被匹配的字符串 //lastMatch $& 最后一个匹配字符串 //lastParen $+ 最后一对圆括号内的匹配子串 //leftContext $` 最后一次匹配前的子串 //multiline $* 用于指定是否所有的表达式都用于多行的布尔值 //rightContext $' 在上次匹配之后的子串 /*使用静态属性*/ //var pattern = /(g)oogle/ig; //var str = 'This is google!'; //pattern.test(str); //执行一下 //alert(RegExp.input); //This is google! //alert(RegExp.leftContext); //This is //alert(RegExp.rightContext); //! //alert(RegExp.lastMatch); //google //alert(RegExp.lastParen); //g //alert(RegExp.multiline); //false //global Boolean 值,表示g 是否已设置 //ignoreCase Boolean 值,表示i 是否已设置 //lastIndex 整数,代表下次匹配将从哪里字符位置开始 //multiline Boolean 值,表示m 是否已设置 //Source 正则表达式的源字符串形式 /*使用实例属性*/ //var pattern = /google/ig; //alert(pattern.global); //true,是否全局了 //alert(pattern.ignoreCase); //true,是否忽略大小写 //alert(pattern.multiline); //false,是否支持换行 //alert(pattern.lastIndex); //0,下次的匹配位置 //alert(pattern.source); //google,正则表达式的源字符串 //var pattern = /google/g; //var str = 'google google google'; //pattern.test(str); //google,匹配第一次 //alert(pattern.lastIndex); //6,第二次匹配的位 // 获取控制 // 正则表达式元字符是包含特殊含义的字符。它们有一些特殊功能,可以控制匹配模式的 // 方式。反斜杠后的元字符将失去其特殊含义。 // 字符类:单个字符和数字 // 元字符/元符号匹配情况 // . 匹配除换行符外的任意字符 // [a-z0-9] 匹配括号中的字符集中的任意字符 // [^a-z0-9] 匹配任意不在括号中的字符集中的字符 //\d 匹配数字 //\D 匹配非数字,同[^0-9]相同 //\w 匹配字母和数字及_ //\W 匹配非字母和数字及_ // 字符类:空白字符 // 元字符/元符号匹配情况 //\0 匹配null 字符 //\b 匹配空格字符 //\f 匹配进纸字符 //\n 匹配换行符 //\r 匹配回车字符 //\t 匹配制表符 //\s 匹配空白字符、空格、制表符和换行符 //\S 匹配非空白字符 // 字符类:锚字符 // 元字符/元符号匹配情况 // ^ 行首匹配 // $ 行尾匹配 //\A 只有匹配字符串开始处 //\b 匹配单词边界,词在[]内时无效 //\B 匹配非单词边界 //\G 匹配当前搜索的开始位置 //\Z 匹配字符串结束处或行尾 //\z 只匹配字符串结束处 // 字符类:重复字符 // 元字符/元符号匹配情况 // x? 匹配0 个或1 个x // x* 匹配0 个或任意多个x // x+ 匹配至少一个x // (xyz)+ 匹配至少一个(xyz) // x{m,n} 匹配最少m 个、最多n 个x // 字符类:替代字符 // 元字符/元符号匹配情况 // this|where|logo 匹配this 或where 或logo 中任意一个 // 字符类:记录字符 // 元字符/元符号匹配情况 // (string) 用于反向引用的分组 //\1 或$1 匹配第一个分组中的内容 //\2 或$2 匹配第二个分组中的内容 //\3 或$3 匹配第三个分组中的内容 //var pattem = /[a-z][A-Z]+/; //var str = 'gOOGLE'; //alert(pattem.test(str)); //var pattern = /8(.*)8/; //var str = 'This is 8google8'; //var result = str.replace(pattern, '<strong>$1</strong>'); //得到替换的字符串输出 //document.write(result); // 贪婪 惰性 // + +? // ? ?? // * *? // {n} {n}? // {n,} {n,}? // {n,m} {n,m}? /*关于贪婪和惰性*/ //var pattern = /[a-z]+?/; //?号关闭了贪婪匹配,只替换了第一个 //var str = 'abcdefjhijklmnopqrstuvwxyz'; //var result = str.replace(pattern, 'xxx'); //alert(result); //var pattern = /8(.+?)8/g;//禁止了贪婪,开启了全局 //var str = 'This is 8google8,That is 8google8,There is 8google8'; //var result = str.replace(pattern, '<strong>$1</strong>'); //document.write(result); //var pattern = /8([^8]*)8/g;//另一种禁止贪婪 //var str = 'This is 8google8,That is 8google8,There is 8google8'; //var result = str.replace(pattern, '<strong>$1</strong>'); //document.write(result); /*使用exec 返回数组*/ //var pattern = /^[a-z]+\s[0-9]{4}$/i; //var str = 'google 2012'; //alert(pattern.exec(str)); //返回整个字符串 //var pattern = /^[a-z]+/i; //只匹配字母 //var str = 'google 2012'; //alert(pattern.exec(str)); //返回google //var pattern = /^([a-z]+)\s([0-9]{4})$/i; //使用分组 //var str = 'google 2012'; //alert(pattern.exec(str)[0]); //google 2012 //alert(pattern.exec(str)[1]); //google //alert(pattern.exec(str)[2]); //2012 ///*捕获性分组和非捕获性分组*/ //var pattern = /(\d+)([a-z])/; //捕获性分组 //var str = '123abc'; //alert(pattern.exec(str)); //123a,123,a //var pattern = /(\d+)(?:[a-z])/; //非捕获性分组 //var str = '123abc'; //alert(pattern.exec(str));//123a,123 ///*使用分组嵌套*/ //var pattern = /(A?(B?(C?)))/; //从外往内获取 //var str = 'ABC'; //alert(pattern.exec(str)); //ABC,ABC,BC,C ///*使用前瞻捕获*/ //var pattern = /(goo(?=gle))/; //goo 后面必须跟着gle 才能捕获 //var str = 'google'; //alert(pattern.exec(str)); //goo,goo ///*使用特殊字符匹配*/ //var pattern = /\.\[\/b\]/; //特殊字符,用\符号转义即可 //var str = '.[/b]'; //alert(pattern.test(str));//true ///*使用换行模式*/ //var pattern = /^\d+/mg; //启用了换行模式 //var str = '1.baidu\n2.google\n3.bing'; //var result = str.replace(pattern, '#'); //alert(result); //1.检查邮政编码 //var pattern = /[1-9][0-9]{5}/; //共6 位数字,第一位不能为0 //var str = '224000'; //alert(pattern.test(str)); //2.检查文件压缩包 //var pattern = /[\w]+\.zip|rar|gz/; //\w 表示所有数字和字母加下划线 //var str = '123.zip'; //\.表示匹配.,后面是一个选择 //alert(pattern.test(str)); ////3.删除多余空格 //var pattern = /\s|\/\/\w{0,}|\/\/[\u4e00-\u9fa5]{0,}/g; //g 必须全局,才能全部匹配 ////var str = '111 222 333'; //var str = document.documentElement.innerHTML; //var result = str.replace(pattern,''); //把空格匹配成无空格 //document.write(result); ////4.删除首尾空格 //var pattern = /^\s+/; //强制首 //var str = ' goo gle '; //var result = str.replace(pattern, ''); //pattern = /\s+$/; //强制尾 //result = result.replace(pattern, ''); //alert('|' + result + '|'); ////4.删除首尾空格 //var pattern = /^\s*(.+?)\s*$/; //使用了非贪婪捕获 //var str = ' google '; //alert('|' + pattern.exec(str)[1] + '|'); //var pattern = /^\s*(.+?)\s*$/; //var str = ' google '; //alert('|' + str.replace(pattern, '$1') + '|'); //使用了分组获取 ////1.普通函数声明 //function box(num1,num2) { // return num1 + num2; //} ////2.使用变量初始化函数 //var box = function (num1,num2) { // return num1 + num2; //} ////3.使用Function构造函数 //var box = new Function('num1', 'num2', 'return num1 + num2'); //PS:第三种方式我们不推荐,因为这种语法会导致解析两次代码(第一次解析常规 //ECMAScript 代码,第二次是解析传入构造函数中的字符串),从而影响性能。但我们可以通 //过这种语法来理解"函数是对象,函数名是指针"的概念。 ////二.作为值的函数 //ECMAScript 中的函数名本身就是变量,所以函数也可以作为值来使用。也就是说,不 //仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数 //的结果返回。 //function box(sumFunction,num) { // return sumFunction(num);//someFunction //} //function sum(num) { // return num *(num+1)/2; //} //var result = box(sum, 100);//传递函数到另一个函数里 //alert(result); ////三.函数内部属性 //在函数内部,有两个特殊的对象:arguments 和this。arguments 是一个类数组对象,包 //含着传入函数中的所有参数,主要用途是保存函数参数。但这个对象还有一个名叫callee 的 //属性,该属性是一个指针,指向拥有这个arguments 对象的函数。 //function box(num) { // if (num <= 1) { // return 1; // } else { // return num * box(num - 1); //一个简单的的递归 // } //} ////对于阶乘函数一般要用到递归算法,所以函数内部一定会调用自身;如果函数名不改变 ////是没有问题的,但一旦改变函数名,内部的自身调用需要逐一修改。为了解决这个问题,我 ////们可以使用arguments.callee 来代替。 //function box(num) { // if (num <= 1) { // return 1; // } else { // return num * arguments.callee(num-1);//使用callee 来执行自身 // } //} //函数内部另一个特殊对象是this,其行为与Java 和C#中的this 大致相似。换句话说, //this 引用的是函数据以执行操作的对象,或者说函数调用语句所处的那个作用域。PS:当在 //全局作用域中调用函数时,this 对象引用的就是window。 //便于理解的改写例子 //window.color = '红色的'; //全局的,或者var color = '红色的';也行 //alert(this.color); //打印全局的color //var box = { // color : '蓝色的', //局部的color // sayColor : function () { // alert(this.color); //此时的this 只能box 里的color // } //}; //box.sayColor(); //打印局部的color //alert(this.color); //还是全局的 ////引用教材的原版例子 //window.color = '红色的'; //或者var color = '红色的';也行 //var box = { // color: '蓝色的' //}; //function sayColor() { // alert(this.color); //这里第一次在外面,第二次在box 里面 //} //sayColor(); //box.sayColor = sayColor; //把函数复制到box 对象里,成为了方法 //box.sayColor(); ////对于prototype 属性,它是保存所有实例方法的真正所在,也就是原型。这个属性, ////我们将在面向对象一章详细介绍。而prototype 下有两个方法:apply()和call(),每个函数都 ////包含这两个非继承而来的方法。这两个方法的用途都在特定的作用域中调用函数,实际上等 ////于设置函数体内this 对象的值。 //function box(num1,num2) { // return num1 + num2;//原函数 //} //function sayBox(num1,num2) { // return box.apply(this, [num1, num2]);//this表示作用域,这里是window //} //[]表示box所需要的参数 //function sayBox2(num1,num2) { // return box.apply(this, arguments);//arguments对象表示box所需要的参数 //} //alert(sayBox(10, 10));//20 //alert(sayBox2(10, 10));//20 ////call()方法于apply()方法相同,他们的区别仅仅在于接收参数的方式不同。对于call()方 ////法而言,第一个参数是作用域,没有变化,变化只是其余的参数都是直接传递给函数的。 //function box(num1, num2) { // return num1 + num2; //} //function callBox(num1, num2) { // return box.call(this, num1, num2); //和apply 区别在于后面的传参 //} //alert(callBox(10, 10));//20 ////事实上,传递参数并不是apply()和call()方法真正的用武之地;它们经常使用的地方是 ////能够扩展函数赖以运行的作用域。 //var color = '红色的'; //或者window.color = '红色的';也行 //var box = { // color : '蓝色的' //}; //function sayColor() { // alert(this.color); //} //sayColor(); //作用域在window //sayColor.call(this); //作用域在window //sayColor.call(window); //作用域在window //sayColor.call(box); //作用域在box,对象冒充 ////这个例子是之前作用域理解的例子修改而成,我们可以发现当我们使用call(box)方法的 ////时候,sayColor()方法的运行环境已经变成了box 对象里了。 ////使用call()或者apply()来扩充作用域的最大好处,就是对象不需要与方法发生任何耦合 ////关系(耦合,就是互相关联的意思,扩展和维护会发生连锁反应)。也就是说,box 对象和 ////sayColor()方法之间不会有多余的关联操作,比如box.sayColor = sayColor; ////ECMAScript 中所有函数的参数都是按值传递的,言下之意就是说,参数不会按引用传 ////递,虽然变量有基本类型和引用类型之分。 //function box(num) { //按值传递,传递的参数是基本类型 // num += 10; //这里的num 是局部变量,全局无效 // return num; //} //var num = 50; //var result = box(num); //alert(result); //60 //alert(num); //50 ////PS:以上的代码中,传递的参数是一个基本类型的值。而函数里的num 是一个局部变 ////量,和外面的num 没有任何联系。 //下面给出一个参数作为引用类型的例子。 //function box(obj) { //按值传递,传递的参数是引用类型 // obj.name = 'Lee'; //} //var p = new Object(); //box(p); //alert(p.name); //PS:如果存在按引用传递的话,那么函数里的那个变量将会是全局变量,在外部也可 //以访问。比如PHP 中,必须在参数前面加上&符号表示按引用传递。而ECMAScript 没有这 //些,只能是局部变量。可以在PHP 中了解一下。 //PS:所以按引用传递和传递引用类型是两个不同的概念。 //function box(obj) { // obj.name = 'Lee'; // var obj = new Object(); //函数内部又创建了一个对象 // obj.name = 'Mr.'; //并没有替换掉原来的obj //} //var p = new Object(); //box(p); //alert(p.name); ////最后得出结论,ECMAScript 函数的参数都将是局部变量,也就是说,没有按引用传递。 ////虽然typeof 运算符在检查基本数据类型的时候非常好用,但检测引用类型的时候,它就 ////不是那么好用了。通常,我们并不想知道它是不是对象,而是想知道它到底是什么类型的对 ////象。因为数组也是object,null 也是Object 等等。 ////这时我们应该采用instanceof 运算符来查看。 //var box = [1,2,3]; //alert(box instanceof Array); //是否是数组 //var box2 = {}; //alert(box2 instanceof Object); //是否是对象 //var box3 = /g/; //alert(box3 instanceof RegExp); //是否是正则表达式 //var box4 = new String('Lee'); //alert(box4 instanceof String); //是否是字符串对象 ////PS:当使用instanceof 检查基本类型的值时,它会返回false。 ////5.执行环境及作用域 ////执行环境是JavaScript 中最为重要的一个概念。执行环境定义了变量或函数有权访问的 ////其他数据,决定了它们各自的行为。 ////全局执行环境是最外围的执行环境。在Web 浏览器中,全局执行环境被认为是window ////对象。因此所有的全局变量和函数都是作为window 对象的属性和方法创建的。 //var box = 'blue'; //声明一个全局变量 //function setBox() { // alert(box); //全局变量可以在函数里访问 //} //setBox(); //执行函数 ////全局的变量和函数,都是window 对象的属性和方法。 //var box = 'blue'; //function setBox() { // alert(window.box); //全局变量即window 的属性 //} //window.setBox(); //全局函数即window 的方法 ////PS:当执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和 ////函数定义也随之销毁。如果是全局环境下,需要程序执行完毕,或者网页被关闭才会销毁。 ////PS:每个执行环境都有一个与之关联的变量对象,就好比全局的window 可以调用变量 ////和属性一样。局部的环境也有一个类似window 的变量对象,环境中定义的所有变量和函数 ////都保存在这个对象中。(我们无法访问这个变量对象,但解析器会处理数据时后台使用它) ////函数里的局部作用域里的变量替换全局变量,但作用域仅限在函数体内这个局部环境。 //var box = 'blue'; //function setBox() { // var box = 'red'; //这里是局部变量,出来就不认识了 // alert(box); //} //setBox(); //alert(box); //red blue ////通过传参,可以替换函数体内的局部变量,但作用域仅限在函数体内这个局部环境。 //var box = 'blue'; //function setBox(box) { //通过传参,替换了全局变量 // alert(box); //} //setBox('red'); //alert(box); ////函数体内还包含着函数,只有这个函数才可以访问内一层的函数。 //var box = 'blue'; //function setBox() { // function setColor() { // var b = 'orange'; // alert(box); // alert(b); // } // setColor(); //setColor()的执行环境在setBox()内 //} //setBox(); ////PS:每个函数被调用时都会创建自己的执行环境。当执行到这个函数时,函数的环境 ////就会被推到环境栈中去执行,而执行后又在环境栈中弹出(退出),把控制权交给上一级的执 ////行环境。 ////PS:当代码在一个环境中执行时,就会形成一种叫做作用域链的东西。它的用途是保 ////证对执行环境中有访问权限的变量和函数进行有序访问。作用域链的前端,就是执行环境的 ////变量对象。 ////内存问题 ////JavaScript 具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使 ////用的内存。其他语言比如C 和C++,必须手工跟踪内存使用情况,适时的释放,否则会造 ////成很多问题。而JavaScript 则不需要这样,它会自行管理内存分配及无用内存的回收。 ////JavaScript 最常用的垃圾收集方式是标记清除。垃圾收集器会在运行的时候给存储在内 ////存中的变量加上标记。然后,它会去掉环境中正在使用变量的标记,而没有被去掉标记的变 ////量将被视为准备删除的变量。最后,垃圾收集器完成内存清理工作,销毁那些带标记的值并 ////回收他们所占用的内存空间。 ////垃圾收集器是周期性运行的,这样会导致整个程序的性能问题。比如IE7 以前的版本, ////它的垃圾收集器是根据内存分配量运行的,比如256 个变量就开始运行垃圾收集器,这样, ////就不得不频繁地运行,从而降低的性能。 ////一般来说,确保占用最少的内存可以让页面获得更好的性能。那么优化内存的最佳方案, ////就是一旦数据不再有用,那么将其设置为null 来释放引用,这个做法叫做解除引用。这一 ////做法适用于大多数全局变量和全局对象。 //var o = { // name : 'Lee' //}; //o = null; //解除对象引用,等待垃圾收集器回收 //var box = document.getElementById('box'); //alert(box.children.length); ////关系掩码表 ////掩码节点关系 ////1 无关(节点不存在) ////2 居前(节点在参考点之前) ////4 居后(节点在参考点之后) ////8 包含(节点是参考点的祖先) ////16 被包含(节点是参考点的后代) ////PS:为什么会出现20,那是因为满足了4 和16 两项,最后相加了。为了能让所有浏览 ////器都可以兼容,我们必须写一个兼容性的函数。 ////传递参考节点(父节点),和其他节点(子节点) //function contains(refNode, otherNode) { // //判断支持contains,并且非Safari 浏览器 // if (typeof refNode.contains != 'undefined' && // !(BrowserDetect.browser == 'Safari' && BrowserDetect.version < 3)) { // return refNode.contains(otherNode); // //判断支持compareDocumentPosition 的浏览器,大于16 就是包含 // } else if (typeof refNode.compareDocumentPosition == 'function') { // return !!(refNode.compareDocumentPosition(otherNode) > 16); // } else { // //更低的浏览器兼容,通过递归一个个获取他的父节点是否存在 // var node = otherNode.parentNode; // do { // if (node === refNode) { // return true; // } else { // node = node.parentNode; // } // } while (node != null); // } // return false; //}
好好学习,天天向上。