JavaScript知识点滴

  • JavaScript的函数参数仅仅具有指示作用, 在实际调用中, 你可以给一个函数传任意个参数. 当然, 如果函数体内需要某个参数, 而你没有传, 调用可能就不能按预期的方式进行; 反之, 传递多余的参数, 函数在执行过程中根本不会管他. 但是如果函数定义的时候加进了参数检测机制, 意味着, 传递任意个参数可能都是有意义的. 在C里面, 这叫做变参函数. 当然JavaScript的函数参数远比C灵活, 可以用以下方式取得函数的参数.

    function param_test(){
    	alert("参数个数:"+arguments.length);
    	for(i=0;i<arguments.length;i++){
    		alert("参数"+i+"的值:"+arguments[i]);
    	}
    }
    param_test("first","second","third");
  • JavaScript不要求变量声明, 但是它使用了一个非常雷人的规则, 就是在函数内部使用var声明的变量是局部变量, 而没有声明的变量是全局变量. 在函数内部不使用任何关键字(也就是没有任何指示)的情况下, 变量默认是全局变量, 只能说, JavaScript太喜欢全局变量了. 但是实际当中, 我们使用的局部变量远比全局变量多. 这个规则改成局部使用一个global关键字声明全局变量比较好, 还有, 既然无需声明, 局部使用全局变量的时候应该指示一下, 以免不小心和一个全局变量同名了, PHP就是这样做的. 当然了, 一个流行的语言, 是无法更改规则的, 不得不考虑人们已经形成的习惯, 和兼容性.

  • 小经验     服务器对于死循环会给予断开处理, 但是对于递归调用导致的堆栈溢出, 在非调试模式下没有明确指示, 而结果是不可预知的, 也就是你可能遇到各种无法解释的现象, 因为堆栈溢出导致变量可能失效, 这时候调试信息是不能作准的.

  • 使用JavaScript动态加载另一个JS脚本, 有三种方式:

    //1.
    <script type="javascript"> 
        document.write("<script src='test.js'><\/script>"); 
    </script>
    //2.
    <script src='' id="s1"></script> 
    <script type="javascript"> 
        s1.src="test.js" //重新设置源JS文件.
    </script>
    //3. 
    <script language="javascript"> 
     var oHead = document.getElementsByTagName('HEAD').item(0); 
        var oScript= document.createElement("script"); 
        oScript.type = "text/javascript"; 
        oScript.src="test.js"; 
        oHead.appendChild( oScript); 
    </script>

    但是这些加载都是动态的, 也就是说, 脚本执行完后, 不一定保证JS已经真的加载完成, 毕竟需要从服务器下载脚本数据. 可以使用XMLHttpRequest方法, 把需要加载的JS下载下来, 再使用方法3把下载的文本设置为script对象的text属性. 因为XMLHttpRequest对象在下载完成后会触发一个事件, 我们需要把后续执行放在这个事件回调里, 而不是原来的脚本执行序列里. XMLHttpRequest的用法, 另行介绍.

    网页尽量使用一个JS文件和CSS文件, 且在头部加载, 浏览器加载网页时, 遇到脚本, 会等待脚本加载, 因为脚本完全可能导致页面非常大的行为差异, 所以干脆优先处理脚本. 脚本文本一般即使有几十K大小(这一般很大了), 加载是很快的. 网页主要的延时在于不同的文件请求和图像视频flash等数据大户, 而且少用外部链接. 所以动态加载不同的CSS和JS脚本尽量不要使用, 因为写在一个文件里, 反倒更节省资源.

  • JavaScript的面向对象和继承, 这一点另写了一篇文章:论JavaScript和C/C++的想通之处

  • 对象拷贝 JavaScript没有提供复制一个对象的方法, 事实上, 你确实很少需要这么做, C++要特别小心的使用对象复制操作, 因为对象可能很复杂, 简单的复制成员是不行的. 虽然如此, 也不是没有这种需求, JavaScript的很多内置对象提供了复制和克隆函数, 自定义对象, 也可以定义给一个克隆函数, 需要的话, 就调用它. 

  • 闭包    在理解了JavaScript的函数其实就是C++的类之后, 闭包就非常简单了. 闭包就是一个定义在函数内部的函数, 和定义在外部不同, 它们不是全局的, 即使这个函数被执行, 定义在它内部的函数也不能在外部被直接从函数名调用它. 但是可以通过把它赋值给外部能访问的变量或者父函数返回它这种方式来访问它. 闭包特殊的地方在于, 闭包一旦创建完成, 和父函数就没有任何关系了, 但是每调用一次父函数(包括直接调用和 new 创建实例的调用) 闭包就会创建一分父函数的局部变量, 这就导致父函数成为了一个类似C++类定义的东西, 闭包使用的变量是保存在自己内部的, 而不是父函数内部. 

    我们知道, 一个对象的属性既可以是数据对象, 也可以是函数, 而对象的函数可以通过obj.func这种方式调用, 而func内部通过this指针可以访问对象的任何属性, 这本质上已经完成了类的功能. 闭包实际上做的是类似的事情, 只不过使用了另一种规则和方式, 但是本质是相同的, 而且闭包不允许外部访问它保存的对象, 所以又类似于C++ private的功能.

    function A(){
    	var i = 0;
    	this.f1 = function(){
    		return ++i;
    	}
    	this.f2 = function(){
    		return ++i;
    	}
    }
    var a = new A();
    alert(a.f1());
    alert(a.f2());

    如果把function A() 换成class A, 并且把f1,f2前面的this去掉, 你会发现, 这就是C++的类定义, 连调用方式都一样!!!相同的功能用属性来实现:
    var a = new Object();
    a.i = 0;
    a.f1 = function(){
    	return ++this.i;
    }
    a.f2 = function(){
    	return ++this.i;
    }
    alert(a.f1());
    alert(a.f2());
    //把上述定义语句合成一个A函数.
    function A(){
    	this.i = 0;
    	this.f1 = function(){
    		return ++this.i;
    	}
    	this.f2 = function(){
    		return ++this.i;
    	}
    }
    a = new A();
    alert(a.f1());
    alert(a.f2());
    上述方式和闭包的区别在于, 闭包没有向实例添加属性, 那么外部就无法访问那些变量. 闭包的实质就是允许在函数内部定义函数, 这个特性的结果就是能够构造一个封闭特性的隐藏对象, 访问这些数据, 只能通过闭包对应的函数, 这也是闭包名称的由来.

你可能感兴趣的:(JavaScript,c)