四种调用模式之函数调用模式

在看了《javascript的语言精粹》中的4.3节函数的调用之后,对其中的函数调用模式很不解,自己写了个小代码,测试了一下,果真如作者所言。赶紧记下来,免得以后忘了。

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
    <body>
        <script type="text/javascript">
            this.name = '全局名';
            var obj = { name:'对象名'};
            obj.sayName = function () {
                alert(this.name);//输出'对象名'
                function inner() {
                    alert(this.name);//输出'全局名'
                }
                inner();
            };
            obj.sayName();
        </script>
    </body>
</html>
作者说这是语言设计上的错误,貌似也只能这样理解了。以后有了新的理解再重新更正过来。

以下是避免这种错误的正确写法,即把指向对象的this指针保存到一个变量中:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
    <body>
        <script type="text/javascript">
            this.name = '全局名';
            var obj = { name:'对象名'};
            obj.sayName = function () {
                var self = this;
                alert(self.name);//输出'对象名'
                function inner() {
                    alert(self.name);//输出'对象名'
                }
                inner();
            };
            obj.sayName();
        </script>
    </body>
</html>

顺便贴出js语言精粹中的另外三种调用模式

1)方法调用模式 
当一个函数被保存为对象的一个属性时, 我们称它为一个方法. 当一个方法被调用时, this 被绑定到该 
对象. 如果一个调用表达式包含一个属性存取表达式(即一个 . 点表达式或[subscript]下标表达式), 那 
么它被当作一个方法来调用. 

// new myObject. 它有一个 value 属性和一个 increment 方法.
// increment 方法接受一个可选的参数. 如果参数不是数字, 那么默认使用数字 1.
var myObject = {
	value: 0;
	increment: function (inc) {
		this.value += typeof inc === 'number' ? inc : 1;
	}
};
myObject.increment();
document.writeln(myObject.value); // 1
myObject.increment(2);
document.writeln(myObject.value); // 3
方法可以使用 this 去访问对象, 所以它能从对象中取值或修改该对象. this 到对象的绑定发生在 
调用的时候. 这个"超级"迟绑定(very late binding) 使得函数可以对 this 高度复用. 通过 this 
可取得它们所属对象的上下文的方法称为公共方法. 

3)构造器调用模式 
Javascript 是一门基于原型继承的语言. 这意味着对象可以直接从其他对象继承属性. 该语言 
是无类别的. 
这偏离了当今编程语言的主流. 当今大多数语言都是基于类的语言. 尽管原型继承有着强大的表现 
力, 但它并不被广泛理解. Javascript 本身对其原型的本质也缺少信心, 所以它提供了一套基于 
类的语言类似的对象构建语法. 有类型化语言编程经验的程序员们很少有愿意接受原型继承的,并 
认为借鉴类型化语言的语法模糊了这门语言真实的原型本质. 真是两边都不讨好.. 
如果在一个函数前面带上 new 来调用, 那么将创建一个隐藏连接到该函数的 prototype 成员的 
新对象, 同时 this 将会被绑定到那个新对象上. 
new 前缀也会改变 return 语句的行为. 

// 创建一个名为 Quo 的构造器函数. 它构造一个带有 status 属性的对象.
var Quo = function(string) {
	this.status = string;
};
// 给 Quo 的所有实例提供一个名为 get_status 的公共方法
Quo.prototype.get_status = function() {
	return this.status;
};
//构造一个 Quo 实例
var myQuo = new Quo("confused");
document.writeln(myQuo.get_status()); // confused
目的就是结合 new 前缀调用的函数被称为构造器函数. 按照约定, 它们保存在以 
大写格式命名的变量里. 如果在调用构造器函数时没有在前面加上 new, 可能会发 
生非常糟糕的事情, 既没有编译时警告, 也没有运行时警告, 所以大写约定非常重要. 
我不推荐使用这种形式的构造器函数. 

4)Apply 调用模式 
因为 Javascript 是一门函数式的面向对象编程语言, 所以函数可以拥有方法. 
apply 方法让我们构建一个参数数组并用其去调用函数. 它也允许我们选择 this 的值. 
apply 方法接收两个参数.  第一个是将被绑定给 this 的值. 第二个就是一个参数数组. 

// 构造一个包含两个数字的数组, 并将它们相加.
var array = [3, 4];
var sum = add.apply(null, array); // sum == 7
// 构造一个包含 status 成员的对象.
var statusObject = {
	stutus: 'A-OK'
};
// statusObject 并没有继承自 Quo.prototype, 但我们可以在 statusObject 上调用
// get_status 方法, 尽管 statusObject 并没有一个名为 get_status 的方法.
var status = Quo.prototype.get_status.apply(statusObject);// status == 'A-OK'



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值