JavaScript中的值传递和toString

一关于值传递和引用传递

JavaScript中只有值传递。

假设有引用ref引用到了对象obj,那么此时引用ref中的数据就是obj的地址。

按照值传递的观念,是把引用ref中存储的数据值,也即是obj的地址传递给一个函数。

按照引用传递的观念,是把引用ref传递给另一个函数,这里把引用传递个另一个函数实际上是把引用本身的地址(不是引用保存的数据值)传递给另一个函数。

值传递:

形参是实参的拷贝,改变形参的值并不会影响外部实参的值。从被调用函数的角度来说,值传递是单向的(实参->形参),参数的值只能传入,

不能传出。当函数内部需要修改参数,并且不希望这个改变影响调用者时,采用值传递。

指针传递:

形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作

引用传递:

形参相当于是实参的“别名”,对形参的操作其实就是对实参的操作,在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过

栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

二  问题的引出

如下一段JavaScript代码

        $(function () {





            var str="abc";
            var obj=new String(str);
            function newToString(){
                return "hello,world";

            }
            function func(val){

                val.toString=newToString();
            }

            func(str);
            alert(str);
            func(obj);

            alert(obj);

        })

上面的运行结果显示 两次都是输出 abc

三 ,解释说明

在上面的这段javascript代码中,我们分别创建了一个字符串值和一个字符串对象。然后分别将这两个数据传递到func方法中。

(1)对于字符串值str来说,调用func方法 的时候会将该值传递到函数中,

 val.toString

这行代码首先是系统为str包装一个String对象,然后给该对象的toString属性赋值为newToString方法的返回值(表述不准确,见下文)。然后当这行代码执行结束之后这个包装string对象就被销毁了。因此在以后的代码中我们也没有办法或者这个系统包装生成的string对象。所以为这个包装对象设置的toString属性值也就没办法在以后代码中获取。

alert(str)的时候系统也会自动为str再次生成一个String包装对象,然后调用该包装对象的toString属性所以引用的方法,也就是调用了toString(),最终输出abc。

(2)对于obj对象来说,会复杂一些。

现在有一个问题需要思考,我们知道所有的js对象都有一个toString()方法,string类型的对象也有toString方法,按照我个人的理解toString实际上是js原型对象的一个属性,然后这个属性引用到了第一个方法,所以我们 可以直接调用toString()方法。

当我们调用方法func(obj)的时候会执行代码:

val.toString=newToString();
 对这行代码的执行结果又两种理解:
        a:因为对象obj的原型对象上面有toString属性,这个属性引用到了一个方法。所以这里的val.toString会定位到原型对象的toString属性,所以这行代码的执行效果就是对更改了原型对象的toString属性为
方法的返回值。
       b: 为对象obj增添一个属性toString,而不更改原型属性
 
第一种效果中更改了原型对象的属性,会使得所有的string对象的toString属性都不再引用原有方法,而是引用到了newToString()方法的返回值。
 
在实际的运行中是采用了第二种方式,也即是为obj对象增添toString属性。原因是在原型继承中,可以通过实例访问原型的属性,但是不可以通过实例更改原型的属性。这样obj对象就增添了一个toString属性,并且他的
原型对象中存在着toString属性,该属性引用到了一个方法。
 
那么接下来的问题是:
alert(obj)是如何做到输出abc的?
按照我个人的理解,系统首先在obj上寻找toString属性,并且可以在实例对象obj上找到该属性,但是这个属性引用的是一个String对象,而不是方法,所以无法将其作为方法调用。然后系统会继续向上寻找一个类型为Function的
toString属性,可以在原型对象上面找到。所以会输出abc,而不是“helloworld”。
在这个过程中我们应该注意到obj有两个toString属性,一个是字符串对象,一个是原型对象上面的函数对象。在调用alert(obj)的时候可以准确定位调用到toString()函数。

四  补充扩展
 
修改代码如下:
function func(val){

    val.toString=newToString;
}

在上面的代码中我们景val的toString属性赋值为一个函数对象,而不是函数的返回值。然后调用 func(obj)和alert(obj),此时根据上面的讲解我们知道obj实例对象上有一个toString属性引用到了newToString函数,原型对象上
有toString属性应用到了另一个函数,所以在这里alert将会输出"helloword"
 
不喜欢写博客,太麻烦
 
 
 
 
 



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值