Fork me on GitHub

初识JavaScript

开始记录东西了,文章主要记录一些基础知识点但笔者认为很必要的东西,所以很多时候内容没有过多的解释,这里只是汇总一下,参考《Javascript高级程序设计》。
标签的位置

一般情况下,所有的<script>元素都应该放在页面的<head>元素中 如下:

<head>
    <title></title>
    <script src="Common/Script/common.js"type="text/javascript"></script>
    <script type="text/javascript">
      //do something
    </script>
</head>
<body>       
    <script src="Common/Script/common.js"type="text/javascript"></script>  //引用到<body>元素中
</body>

上述做法,意味着必须要等到全部的JavaScript代码都被下载,解析完成后,才能呈现页面,对于一些需要很多脚本的页面,会导致页面出现延迟,浏览器会出现空白,为了避免这个问题很多时候把JavaScript引用到<body>元素中,这样用户体验会好些.

HTML4.01为<srcipt>定义了defer属性,同样可以实现上述效果,
<script src="common/jquery-1.7.2/jquery-1.7.2.js" type="text/javascript" defer="defer"></script>但不是所有浏览器都支持这个属性。后文将说到JS延迟加载的一些方式 !

JavaScript的变量类型
JavaScript的变量分为基本类型和引用类型.基本数据类型是直接存在栈空间的简单数据段,这种类型直接将值保存在内存的某个位置.引用数据类型存储的是指向实际存储于堆内存中的对象的地址.
JavaScript中的基本数据类型共有五种:Number,Null,Undefined,Boolean和String.需要注意的是,js中的String是基本数据类型.
对于基本类型变量的访问,是按值访问的,而对于引用变量的访问是按引用访问的.
动态属性
对于引用数据类型的变量,可以对其添加属性和方法,也可以删除属性和方法,例如:

var p = new Object(); 
p.name = "张三"; 
alert(p.name);//张三


但是对于基本数据类型来说,这样是不允许的,如下:

var str = "张三"; 
str.age = 20; 
alert(str.age);//undefined

复制变量
对于基本类型的变量,从一个变量向另一个变量复制,实际上是将第一个变量存储的值复制给另一个变量。因此,复制完成之后,对第一个变量进行修改,修改操作不会影响另一个变量的值。例如:

var num1 = 1; 
var num2 = num1; 
alert(num2);//1 
num1 = 2; 
alert(num2);//1

但是对于引用数据类型,将一个变量复制给另一个变量,实际上是存储第一个变量所存储的地址拷贝给另一个变量,换句话说,这两个变量之后就指向同一块内存空间。因此,接下来对第一个变量的操作也会影响第二个变量。例如:

var p1 = newObject(); 
p1.name = "张三"; 
p1.age = 20; 
var p2 = p1; 
alert(p2.age);//20 
p1.age = 30; 
alert(p2.age);//30

参数传递
JavaScript的参数传递全部是按值传递。也就是说,将函数外部的值复制给函数的参数。对于基本类型来说,和变量的复制是一样的,对于引用数据类型,则如同引用数据类型的复制一样。下面分别举例说明:

function inc(num) { 
 num += 1; 
 } 
var i = 10; 
alert(i);//10 
inc(i); 
alert(i);//10

对于基本类型变量i,将其传递给函数inc,实际上是将其值10传递给函数inc的参数,在函数内部,对其内部的变量进程加1操作,因此不会影响i。
function setName(obj) {
  obj.name = "张三";
}
var person = newObject();
setName(person);
alert(person.name);//张三

将person传递给函数setName,于是将person所指向的堆内存地址传递给函数的参数,因此,参数指向的内存和person指向的内存是同一个地址。因此在函数内部修改该地址指向对象的内容也会反映到person上来。

检测变量的类型
检测基本类型,使用typeof运算符即可,例如:

var s = "张三"; 
 var b = true; 
 var i = 20; 
 var u; 
 var n = null; 
 var o = new Object(); 
 alert(typeof s);//string 
 alert(typeof b);//boolean 
 alert(typeof i); //number 
 alert(typeof u); //undefined 
 alert(typeof n); //object 
 alert(typeof o); //object
//但是,在检测引用数据类型方面,typeof并不给力,需要使用instanceof运算符:
alert(person instanceof Object);//person是不是Object类型的?

变量作用域
js的作用域主要有两种:全局作用域和局部作用域。值得一提的是,在js中,没有块级作用于。例如:

for(var i = 0; i < 10; i++) { 
 //do sth 
 } 
 alert(i);//10
//以上面的代码为例,for语句块不存在一个特别的作用域,因此在for循环之外,i依然可以被访问到。同理,对于if-else语句也是这样的。
 if(true) { 
 color = "red"; 
} 
 alert(color);//red

this是谁

把this看成当前对象,是最常见到的用法,也是最容易理解的
如:
<input type="button" value="我是谁?" onclick="this.value='我是中国人!'"/>
这里当按钮被触发时,this指向当前这个button对象。value值随之改变。
如:

function Person(){
  this.name ="I am Irving”;
}
 var f =new Person();
 alert(f.name);

这里的this指向当前的实例对象。
指向当前的对象直接量

var o = {
   name:"I am Irving", 
   me:function()
   return this; }
 }
 var newObj = o.me();  //这里调用me方法,返回this,也就是当前对象直接量o13 14 alet(newObj.name);复制代码


以上的都是this对象作用域的范畴,下面指出什么时候出现全局作用域的情况

普通函数的调用
细心的人会发现,所谓的f()只不过是window.f()的简写,所以this指的是全局对象window,因此alert(name)相当于alert(window.name);
这里稍稍修改一下,把f()换成new f();即实例化对象。则此时this则是指向当前实例对象。
原因是使用new运算符实例化函数f()后,则创建了一个新的对象,当前的作用域就不是全局作用域了,而是变回对象作用域。

改写下第一个例子为:

修改前:
<input type="button" value="我是谁?" onclick="this.value='我是中国人!'"/>
修改后:
<input type="button" value="我是谁?" onclick="f()"/>    
<script>    
function f(){
this.value ="我是中国人!";
}    
</script>

运行后你会发现,按钮的value值没有变化,也就是说,这里使用直接调用函数的方法,this处于全局作用域中,仍然指向window对象。
再变形一下:

<input type="button" value="我是谁?"/>
      <script>
        var btn = document.getElementsByTagName("input").[0];
        btn.onclick = f;    //注意这里是f,而不是f()
        function f(){
          this.value ="I am Irving”;
        }
          </script>

this又重新变为对象作用域,指向当前按钮对象.
总结:
1.引用后,再执行,作用域发生变化,this指向执行的对象
  2.直接调用执行,作用域保持不变,this指向定义它的对象

判断是否为IE
1.监听事件 addEventListener
if (window.attachEvent) {
            alert("IE");
        }
        else {
            alert("Not IE");
        }
2.document.all
  if (document.all && navigator.userAgent.indexOf('Opera') === -1) {
            alert("IE");
        }
        else {
            alert("Not IE");
        }
3.navigator
  if (navigator.appName == "Microsoft Internet Explorer") {
            alert("IE")
        } else {
            alert("Not IE " + navigator.appName)
        }
4.event

  if (typeof event !== 'undefined') {
            alert("IE");
        }
        else {
            alert("Not IE");
        }
5.  垂直制表符(不适用IE9)

通过IE与非IE浏览器对垂直制表符支持 var ie = !+"\v1"; 原文:2 bytes, ehr ... 9, ehr ... 7!!! to know if your browser is IE(需FQ)
后被俄国人以6byte的长度刷新纪录,如"利用了IE与标准浏览器在处理数组的toString方法的差异做成的。对于标准游览器,如果数组里面最后一个字符为逗号,JS引擎会自动剔除它

if(!-[1,]){
 alert('是IE!') }
else{
 alert('非IE!')
 }

6.createEvent(不适用IE9)

    if (!document.createEvent) {
            alert("IE");
        }
        else {
            alert("Not IE");
        }

 

7.event(需要包含window中)

 window.onload = function () {
            if (window.event) {
                alert("IE");
            }
            else {
                alert("Not IE");
            }
        }

意:需要说明一下的是五六二种的方式不适用IE9 一般使用第一种与第四种即可,第七种留意

文档模式

如IE9中的开发人员工具可以切换IE渲染当前页面的模式,即文档类型,默认是Quirks mode(混杂模式),另外几种是Standards mode(标准模式),不同的模式页面的样式也不同,同样也会影响到JS的解释执行,如上述验证是否是IE的浏览器的第五种方式,若IE是Standards mode ,就会有相反的结果

<noscript>元素

一些浏览器如果禁用了脚本,会导致一些不必要的麻烦,所以一般情况下会验证下

   <noscript>
        <div style="position: absolute; z-index: 100000; height: 2046px; top: 0px; left: 0px;
            width: 100%; background: white; text-align: center;">
            <img src="images/noscript.gif" alt='抱歉,请开启脚本支持!' />
        </div>
    </noscript>

修订记录

2012年6月21日16:40:42  开篇

2012年6月22日15:19:25  修正IE验证

posted @ 2012-06-21 18:48  花儿笑弯了腰  阅读(268)  评论(0编辑  收藏  举报