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;
    //}

 

posted @ 2020-08-18 11:41  流星泪  阅读(214)  评论(0编辑  收藏  举报