web前端之悟透JavaScript二:JavaScript真经(对象)

web前端之悟透JavaScript二:JavaScript真经(对象)

任何一个程序都会在一个原始的环境中开始运行,这个原始的环境就被称为全局环境。全局环境中包含了一些预定义元素,这些元素对于我们的程序来说是自然存在的,他们本来就存在着,我们拿来就可以使用了。
在JavaScript里的全局环境就是一个对象,这个对象是JavaScript运行环境的根。对于浏览器中的JavaScript来说,这个根对象就是我们熟知的window对象。对于全局的JavaScript语句来说,window对象就相当于当前的作用域。
当我们写下:
var myName=”leadzen”;
就是定义了window作用域的一个变量myName,而当我们写下:
myName=”leadzen”;
就是定义了window对象的一个属性myName
这里,“window作用域的一个变量myName”和“window对象的一个属性myName”几乎等价。对于全局的JavaScript语句来说,加不加var都无所谓,但是对于一个函数体内的语句,有没有“var”就要小心了。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>有无var的区别</title>
    <script type="text/javascript">
    var yourName="王菲";
    myName="fzw";
    alert(myName+" like "+yourName);//fzw like 王菲
    ChangeNames();
    function ChangeNames(){
        alert('Your old name is '+yourName);//undefined
        alert('My old name is '+myName);//fzw
        var yourName="张三";
        myName="李四";
        alert(myName+" like "+yourName);//李四 like 张三
    };
    alert(myName+" like "+yourName);//李四 like 王菲
    </script>
</head>
<body>

</body>
</html>

显然使用var修饰的yourName标识符在函数内外是两个东西,外面的“王菲”不会因为使用ChangeNames函数内改成“张三”而改变,回到外面还是“王菲”。而myName没有使用var修饰,就是一个东西了,函数内的修改也能在函数外发生改变。

值得注意的是,changeNames函数中的第一句,我们本来希望最外面的那个yourName的值,但此时的输出却表现为undefined,而第二句myName又是我们希望的值。

解释: var定义的是作用域上的一个变量,而没有var的标识符却可能是全局根对象的一个属性。当代码运行在全局作用域时,作用域就是根对象window,所以,有没有“var”都无所谓。当然,不同的JavaScript执行引擎对此可能有不同的实现方式,但都可以大致这么来理解。

但是当代码运行进入一个函数时,JavaScript会创造一个新的作用域,来作为当前作用域的子作用域。然后,当全局变量作用域切换为一个新建的子作用域,开始执行函数逻辑。JavaScript执行引擎会把此函数内的逻辑代码,当一个代码段单元来分析与执行。

在第一步的预编译分析中,JavaScript执行引擎将所有定义式函数直接创建为作用域上的函数变量,并将其值初始化为定义的函数代码逻辑,也就是为其建立了可调可用的函数变量。而对于所有“var”定义的变量,也会在第一步的预编译中创建起来,并将初始值设为undefined。

随后,JavaScript开始解释执行代码。当遇到函数名或变量名的使用时,JavaScript执行引擎会首先在当前作用域查找函数或变量,如果没有就到上层作用域查找,以此类推。因此,前面的语句引用后面的语句定义的“var”变量时,该变量其实已经存在,只是初始值是undefined。

因此,用var定义的变量只对本作用域有效,尽管此时上层作用域有同名的东西,都与本作用域的var变量无关。退出本作用域之后,此var消失,回到原来的作用域该有啥还是有啥。

王菲就是王菲,她更喜欢父亲取得名字,当回到自己可以控制的作用域时,当然就立马改回来。


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>caller属性</title>
    <script type="text/javascript">
    function WhoCallMe(){
        alert("My caller is "+WhoCallMe.caller);//输出自己的caller
    };
    function CallerA(){
        WhoCallMe();
    };
    function CallerB(){
        WhoCallMe();
    };
    alert(WhoCallMe.caller);//输出null
    WhoCallMe();//输出null
    CallerA();
    CallerB();
    </script>
</head>
<body>

</body>
</html>

如果函数的caller属性是Null,表示函数没有被调用或者是被全局代码调用。函数的caller属性值实际上是动态变化的。函数的初始caller值都是null,当调用一个函数时,如果代码已经运行在某个函数体内,JavaScript执行引擎会将被函数的caller属性设置为当前函数。在退出被调函数作用域时,被调函数的caller属性又会被恢复为null值。

this关键字表示函数正在服务的”这个”对象,后续我们会进行讲述。
arguments对象,从字面上看表示调用当前函数的参数们。除了我们可以直接使用函数参数定义列表中的那些标识符来访问之外,还可以用arguments对象按数组方式来访问参数,尽管arguments对象并非一个真正的数组。
值得注意的是:用eval()函数动态执行的代码并不创建新的作用域,期待吗就是在当前作用域中执行的。eval()中的动态代码可以访问到当前作用域的this,arguments等对象,因此可以使用evel()实现一些高级的多态和动态扩展方面的应用。

现在开始我们的对象之旅:

前面我们说,在JavaScript中只有object和function两种东西才有对象化的能力。任何人一个函数都可以为其动态地添加或取出属性,这些属性可以是简单的类型,可以是对象,可以是其他的函数。也就是说,函数具有对象的全部特征,你完全可以把函数作对象来使用。其实,函数就是对象,只不过比一般对象多了一个“()”操作符,这个操作符用来执行函数的逻辑,即函数本身还可以被调用,一般对象却不可以被调用,除此之外完全相同。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>对象</title>
    <script type="text/javascript">
    function Sing(){
        alert(Sing.author+": "+Sing.poem);
    };
    Sing.author="李白";
    Sing.poem="床前明月光,疑是地上霜。举头望明月,低头思故乡。";
    Sing();
    Sing.author="李时珍";
    Sing.poem="12345,上山打老虎,老虎打不到,打到小松鼠。";
    Sing();

    </script>
</head>
<body>

</body>
</html>

在这段代码中,Sing函数定义之后,又给Sing函数动态添加了author和poem属性。将author和poem属性设为不同的作者和诗句,在调用Sing()时就能显示出不同的结果。通过这个我们理解到了function类型都是和object类型一样的东西,我们称之为对象。

在面向对象的编程里,数据和代码的有机结合就构成了对象的概念。其主要分为两部分:一个是对象内的世界,一个是对象外的世界。对象天生具有自私的一面,外面的世界未经允许是不可访问对象内部的。对象也有大方的一面,他对外提供属性和方法,也为他人服务。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>this</title>
    <script type="text/javascript">
    function WhoAml(){
        alert("I'm "+this.name+" of "+typeof(this));
    };
    WhoAml();//此时this是根对象window,其name属性为空字符串,输出I'm of object
    var BillGates={name:"Bill Gates"};
    BillGates.WhoAml=WhoAml;//将函数WhoAml作为BillGates的方法
    BillGates.WhoAml();//I'm Bill Gates of object.

    var SteveJobs={name:"Steve Jobs"};
    SteveJobs.WhoAml=WhoAml;
    SteveJobs.WhoAml();//I'm Steve Jobs of object.

    WhoAml.call(BillGates);//直接将BillGates作为this,调用WhoAml I'm Bill Gates of object.
    WhoAml.call(SteveJobs);//I'm Steve Jobs of object.
    BillGates.WhoAml.call(SteveJobs);//将SteveJobs作为this,却调用BillGates的方法 I'm Steve Jobs of object.
    SteveJobs.WhoAml.call(BillGates);// I'm Bill Gates of object.
    WhoAml.WhoAml=WhoAml;//将WhoAml函数设置为自身的方法。
    WhoAml.name="WhoAml";
    WhoAml.WhoAml();//此时的this是WhoAml自身 I'm WhoAml of object.

    ({name:"nobody",WhoAml:WhoAml}).WhoAml(); //创建一个匿名对象,并调用这个方法I'm nobody of object.
    </script>
</head>
<body>

</body>
</html>

从上面代码中可以看出,同一个函数可以从不同的角度来调用,this并不一定是函数本身所属的对象。this只是在任意对象和function元素结合的一个概念,这个结合比起一般对象语言的默认结合更加灵活,显得更加超然和洒脱。

我们使用json形式来创建对象:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>如何建立一个对象</title>
    <script type="text/javascript">
    var o={};//创建一个没有任何属性的对象
    var parent={name:"angle",age:18,married:false};//创建一个对象并设置属性及初始值
    var speaker={text:"Hello World",say:function(){alert(this.text)}};//创建一个对象并设置属性和方法。
    var company={
        name:"Microsoft"
        ,product:"soft"
        ,chairman:{name:"Bill Gates",age:53}
        ,employees[{name:"Angel",age:25},{name:"Hanson",age:23}]
        ,readme:function(){
            document.write(this.name+" product"+this.product);
        }
    };

    </script>
</head>
<body>

</body>
</html>

为什么逗号写在最前面,查看详情
json的形式就是用“{}”包括起来的项目列表,每一个项目之间用“,”分隔,而项目就是使用“:”分隔属性名和属性值。对象可以作为一个json形式的字符串,在网络间自由传递和交换信息。当需要使用json字符变成JavaScript对象时,只需要使用eval函数这个强大的数码转化引擎,就立即能得到一个JavaScript内存对象

构造对象:
function MyFunc(){};//定义一个空函数
var anObj1=new MyFunc();//使用new操作符,借助MyFunc函数创建一个对象
var anObj2=new MyFunc;//函数也可以没有括号,但仍然调用该函数

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>Document</title>
    <script type="text/javascript">
    function Person(name){
        this.name=name;
        this.SayHello=function(){
            alert("Hello,I'm"+this.name);
        };
    };
    function Employee(name,salay){
        Person.call(this,name);//调用父构造函数
        this.salay=salay;
        this.ShowMeTheMoney=function(){
            alert(this.name+" $ "+this.salay);
        };
    };
    var BillGates=new Person("Bill Gates");
    var SteveJobs=new Employee("Steve Jobs",1234);

    BillGates.SayHello();
    SteveJobs.SayHello();
    SteveJobs.ShowMeTheMoney();

    alert(BillGates.constructor == Person);
    alert(SteveJobs.constructor == Employee);

    alert(BillGates.SayHello== SteveJobs.SayHello);
    </script>
</head>
<body>

</body>
</html>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编程世界里只存在两种基本元素,一个是数据,一个是代码。编程世界就是在数据和代码千丝万缕的纠缠中呈现出无限的生机和活力。     数据天生就是文静的,总想保持自己固有的本色;而代码却天生活泼,总想改变这个世界。      你看,数据代码间的关系与物质能量间的关系有着惊人的相似。数据也是有惯性的,如果没有代码来施加外力,她总保持自己原来的状态。而代码就象能量,他存在的唯一目的,就是要努力改变数据原来的状态。在代码改变数据的同时,也会因为数据的抗拒而反过来影响或改变代码原有的趋势。甚至在某些情况下,数据可以转变为代码,而代码却又有可能被转变为数据,或许还存在一个类似E=MC2形式的数码转换方程呢。然而,就是在数据和代码间这种即矛盾又统一的运转中,总能体现出计算机世界的规律,这些规律正是我们编写的程序逻辑。     不过,由于不同程序员有着不同的世界观,这些数据和代码看起来也就不尽相同。于是,不同世界观的程序员们运用各自的方法论,推动着编程世界的进化和发展。       众所周知,当今最流行的编程思想莫过于面向对象编程的思想。为什么面向对象的思想能迅速风靡编程世界呢?因为面向对象的思想首次把数据和代码结合成统一体,并以一个简单的对象概念呈现给编程者。这一下子就将原来那些杂乱的算法与子程序,以及纠缠不清的复杂数据结构,划分成清晰而有序的对象结构,从而理清了数据与代码在我们心中那团乱麻般的结。我们又可以有一个更清晰的思维,在另一个思想高度上去探索更加浩瀚的编程世界了。     在五祖弘忍讲授完《对象真经》之后的一天,他对众弟子们说:“经已讲完,想必尔等应该有所感,请各自写个偈子来看”。大弟子神秀是被大家公认为性最高的师兄,他的偈子写道:“身是对象树,心如类般明。朝朝勤拂拭,莫让惹尘埃!”。此偈一出,立即引起师兄弟们的轰动,大家都说写得太好了。只有火头僧慧能看后,轻轻地叹了口气,又随手在墙上写道:“对象本无根,类型亦无形。本来无一物,何处惹尘埃?”。然后摇了摇头,扬长而去。大家看了慧能的偈子都说:“写的什么乱七八糟的啊,看不懂”。师父弘忍看了神秀的诗偈也点头称赞,再看慧能的诗偈之后默然摇头。就在当天夜里,弘忍却悄悄把慧能叫到自己的禅房,将珍藏多年的软件真经传授于他,然后让他趁着月色连夜逃走...     后来,慧能果然不负师父厚望,在南方开创了禅宗另一个广阔的天空。而慧能当年带走的软件真经中就有一本是《JavaScript真经》!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值