这次来点直接的,算是对Javascript的总结吧,到现在为止Javascript的心得也写了不少了,很多体会,也收集了很多博主的博客,也许以后学习的时候,自己的博客和这些收集的博客就是自己常去的地方。
var str = "liuyu";var test = function () { alert(str); alert(this.str); alert(window.str); }test();
上面这个代码很容易理解,这里的str就是全局变量,因为在后面是直接调用函数,所以this指的就是window,所有的全局变量都认识是附加在window对象上的,而window对象我们不可能陌生,也就不多说了,这里有这几个知识点:
1、作用域,Javascript中的作用域是以函数划分开来的,当在函数里面访问变量的时候,如果函数内部没有该变量,那么就在上一个作用域中找,直到找到位置。
2,动态性,Javacript中的对象可以动态的增加属性和方法,定义的变量都相当于是附加在window对象上的,window可以省略。
var str = "liuyu";var test = function () { var str = "test"; alert(str); alert(this.str);}test();
上面这段代码告诉我们,函数内部定义的变量会覆盖函数外部定义的全局变量,其实并不是这么简单,因为在test这个函数的作用域内,已经定义了str变量,既然可以找到那么就不往它的上一级作用域查找。
var test = function () { str = "test"; alert(str); }test();alert(window.str);
上面这段代码告诉我们,函数内所有没有var开始的变量都是全局变量,其实就是附加在window上的。
var test = function () { str = 1; alert(str); alert(window.str); var str = 10; alert(str); alert(window.str);}test();alert(window.str);
这段代码运行的结果,可能会让大家大吃一惊,我在开始运行这段代码的时候也有类似的感觉,其实细细想起来并不是这么复杂,但是如果要深究的话,意味无穷。
这段代码和Javascript的解释和运行有关系的。
Javascript是脚本语言,其过程分为解释(预编译)和运行过程,预编译过程中用于确定变量和函数等,这个时候并不赋值,赋值是在运行阶段的。因为是从上往下运行,所以大家能看到undefined这个语句。
因为在test中定义了var str这个局部变量,这个过程是在预编译阶段中完成的,虽然这个变量定义在最后,赋值是在运行阶段完成。这里要说明一点,就是作用域内的变量不管在函数的哪里声明,javascript都会在函数运行前在作用域内包含该变量。
//下面的代码在window对象中创建一个属于自己的对象或者命名空间,并把自执行函数中的方法附加到这个对象上,以便于我们调用这个自执行函数中的一些功能。 (function() { //根据id获取对象 function _$(id) { return document.getElementById(id); } //创建一个自己的对象相当于C#中的命名空间(javascript中没有命名空间这个说法,刚才已经说了牵强附会)window.liuyu = {}; //将内部函数_setStyle封装在mySpace命名空间内 window.liuyu.$ = _$; })(); //测试代码 window.onload = function() { var divtest=window.liuyu.$("testdiv");} //如果不使用这种方法,那么,下面的方法也可以实现的。 window.liuyu= {}; window.liuyu.$ = function(id) { return document.getElementById(id); } //测试代码 window.onload = function() { var divtest=window.liuyu.$("testdiv"); }
这段代码内容比较大,但是很多都在前面介绍过,这里用到了闭包,闭包可以模拟静态变量类等,可以参阅:。这里还用到了自执行函数,甚至是伪装属于自己的对象,关于这个可以看前面的博客。
public class ThisTest { private int a; private int b; public int Add() { return a + b; } public void SetA(int a) { this.a = a; } public void SetB(int b) { this.b = b; } }
function Add(x, y) { var a = x; var b = y; this.SetA = function (a) { a = a; } this.SetB = function (b) { b = b } this.GetAdd = function () { return a + b; }}var Test = new Add(3, 7)alert(Test.GetAdd())
上面这两段代码是用C#和Javascript做了一个对比,Javascript中没有类,没有共有变量,也就是public等,而只有全局变量和私有变量,但是Javascript可以通过闭包去模拟,函数中的var定义的变量在函数执行完毕后在外部是不能访问的,但是通过返回一个内部的函数就可以了,或者通过this这个关键字去访问,this这个在函数访问的时候就是window,而用new实例化对象的时候这个this就是当前new的这个对象,通过this,就可以在外面访里面的函数,可以将这个称作为“成员变量或者成员函数”,当然这个说法只是我一厢情愿而已,真正的Javascript中是不存在的,在这里只是和C#做了个比较而已。
var str = "2"; Object.prototype.str = "1"; (function Test() { alert(str); })();
上面这个是用自执行函数写的,自执行函数其本质是一个匿名函数,为什么叫这个名称,我没自己深究,大胆猜测下,因为这个函数是可以自动执行的,回想一般的函数,分两个步骤:
1,定义;
2,调用。
这里将两个步骤合二为一了,可以认为是下面的写法:
var FunctionTest = function Test() { alert(str); } FunctionTest();
人有的时候需要大胆猜测,然后去证明或者澄清,这不失为一种学习和自我理解的方法,这个错对不予考究,到此为止,因为这个例子在这里不是用来说这个的。
上面的结果是2,这说明了window的作用域靠近函数的作用域,而Object原型的作用域稍远,当然你可以删除var 这一行,代码也是可以运行的。我们可以得出这样一个顺序,Object.Prototype-window-函数,这也是搜索变量的顺序。
var str = "2"; Object.prototype.str = "1"; Object.str = "3"; (function Test() { alert(str); })();
这个经过测试,顺序是Object-Object.Prototype-window
window.str = "4"; Object.prototype.str = "1"; Object.str = "3"; var str = "2"; (function Test() { alert(str); })();
这个例子的顺序是object-object.Prototype-window-var所定义的,这是因为变量覆盖的原因,因为Javascript在预编译阶段确定变量,如果定义了两个,那么只会用最后一个,大家可以将var 和window的这个反过来试试。
最后推荐一个博客: