初识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验证