`
lucane
  • 浏览: 119044 次
  • 性别: Icon_minigender_1
  • 来自: 江湖
社区版块
存档分类
最新评论

改变函数执行的上下文

阅读更多
参考阅读:js教程:javascript作用域(Scope)

JavaScript中this代表的是运行时的对象,是正在调用代码的对象

在浏览器环境中运行需要把println函数改成alert或者console.log

function gf() {println(this)}


运行这段代码输出:[object global]

下面这段代码人为改变了代码执行的上下文,this也就代表着不同的对象
var obj1 = {count:1};
var obj2 = {count:6};

function foo(factor) {this.count * factor}

foo.call(obj1, 8); // 1 * 8
foo.call(obj2, 8); // 6 * 8


再看
Prototype的bind方法代码
Function.prototype.bind = function() {
    var __method = this, args = $A(arguments), object = args.shift(); // Important
    return function() {
        return __method.apply(object, args.concat($A(arguments)));
    }
}

// 上面这种方法没怎么明白,把arguments转换成Array,然后把执行函数绑定在第一个方法的参数上(把绑定的对象提取出来)
// 绑定参数又增加args.concat($A(arguments)),这多出来的几行代码是什么意图?
// 原来这样是为了
// 在bind函数执行的时候可以添加一次参数
// 然后在后期bind返回的函数执行的时候又可以添加一次参数
// 这样在函数执行的上下文变化时还能“记忆”之前的参数,这就是JS的必包特性
// http://mengjiaoyao.blog.163.com/blog/static/298416192009113102149773/


// 将传入的对象转化成Array
var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
}


早期的Prototype中bind方法更简单明了
Function.prototype.bind = function(object) {
    var method = this; // Important
    return function() {
        method.apply(object, arguments);
    }
}


改写我们上面代码
var foo1 = foo.bind(obj1);
foo1(8);


两次传参的调用代码
var obj1 = {count:1};
var obj2 = {count:6};

function foo(a,b,c) {println(this.count * a * b * c)}


var foo1 = foo.bind(obj1, 2);
var foo2 = foo.bind(obj2, 3);
foo1(5,6);
js>60 // 1 * 2 * 5 * 6
foo2(7,8);
js>1008 // 6 * 3 * 7 * 8


这就是改变函数执行上下文+记忆不同上下文之间参数的结果


如果不想用prototype这种方式的写法的话,可以参考如下代码
var gbind = function(o, f) {
    return function() {
        return f.apply(o, arguments);
    }
};

这种写法如果需要支持更复杂的参数传递的话,想想该怎么写?

虽然看不懂,但每次想这个问题还得看一遍
引用
A "closure" is an expression (typically a function) that can have free variables together with an environment that binds those variables (that "closes" the expression).


以下纯淡腾乱作,请蒙上眼睛
// another version xscript%#%live.com
// 实在没有必要这么写
// bindAsEventListener()返回的函数必须至少带一个参数,那就是event,否则在FF无法运行
Function.prototype.bindAsEventListener = function() {
    var __method = this, args = $A(arguments), object = args.shift();
    return function() {
        var a = $A(arguments), e, evts;
        var __e_m = "警告,您的浏览器必须指定第一个参数类型为事件!";
        // 如果后期传入了参数
        // alert(a.length); // IE和W3C输出的不一样,应该好好学学,理解
        if(0 < a.length) {
            e = a[0];
            // alert(typeof e);
            // alert(e.type);
            // 如果是事件,判断对象是否事件还有待改进
            // 
            if("object" == typeof e && !!e.type && !!e.srcElement) {
                a.shift();
                evts = [e || window.event];
            } else if(!window.event) { // 而且window.event都无法捕捉到
                true == !!console.log ? console.log(__e_m) : alert(__e_m);
                return false;
            } else {
	            evts = [window.event];
            }
        } else {
            if(!!window.event) {
                evts = [window.event]; 
            } else {
                true == !!console.log ? console.log(__e_m) : alert(__e_m);
                return false;
            }
        }
        return __method.apply(object, evts.concat(args).concat(a));
    }
}
分享到:
评论

相关推荐

    this和执行上下文实现代码

    函数的执行上下文由当前的运行环境而定: 1. 全局变量和全局函数附属于全局对象(window),因此使用”var”或”this”两种方法定义全局变量是等效的。 2. 执行上下文和作用域不同。执行上下文在运行时确定,随时可能...

    API之网络函数---整理网络函数及功能

    FindNextPrinterChangeNotification 用这个函数判断触发一次打印机改变通告信号的原因 FreePrinterNotifyInfo 释放由FindNextPrinterChangeNotification函数分配的一个缓冲区 GetForm 取得与指定表单有关的信息 ...

    精通WindowsAPI 函数 接口 编程实例

    5.3.3 使用全局和局部函数分配和释放内存、改变内存块属性 137 5.4 虚拟内存管理 138 5.4.1 虚拟地址空间与内存分页 139 5.4.2 分配和释放可读可写的虚拟内存页面 139 5.4.3 修改内存页面状态和保护属性、...

    精通Windows.API-函数、接口、编程实例.pdf

    5.3.3 使用全局和局部函数分配和释放内存、改变内存块属性 137 5.4 虚拟内存管理 138 5.4.1 虚拟地址空间与内存分页 139 5.4.2 分配和释放可读可写的虚拟内存页面 139 5.4.3 修改内存页面状态和保护属性、...

    javascript中利用柯里化函数实现bind方法【推荐】

    利用函数执行可以形成一个不销毁的作用域的原理,把需要预先处理的内容都储存在这个不销毁的作用域中,并且返回一个小函数,以后我们执行的都是小函数,在小函数中把之前预先存储的值进行相关的操作处理即可;...

    VC++常用的共用函数100多页

    问:CFormView中的上下文帮助? 80 问:CArchive类的WriteObject函数问题? 80 问:RegisterWindowMessage中的BroadcastSystemMessage如何处理? 80 问:CListCtrl中选择变化时如何获得通知? 81 问:如何向ATL-COM对象...

    基于pj.js实现的日历选择控件,文本框日期选择.rar

    date:默认开始日期,不需要可以是null(以当天日期开始),yearListLength:年份下拉列表长度,当改变年份或者月份是的事件监听器,以当前Calendar对象为上下文执行fn函数,当选择日期时触发的函数,以当前Calendar对象为...

    JavaScript函数apply()和call()用法与异同分析

    这两个方法的作用是在函数调用时改变函数的执行上下文,也就是函数内的this,apply()方法接收两个参数,一个是在其中运行函数的作用域,另一个可以是arguments对象,也可以是参数数组。 call()方法与apply()方法的作

    javascript中利用柯里化函数实现bind方法

    利用函数执行可以形成一个不销毁的作用域的原理,把需要预先处理的内容都储存在这个不销毁的作用域中,并且返回一个小函数,以后我们执行的都是小函数,在小函数中把之前预先存储的值进行相关的操作处理即可;...

    跟我学习javascript的call(),apply(),bind()与回调

    简单的说就是改变函数执行的上下文,这是最基本的用法。两个方法基本区别在于传参不同。 call(obj,arg1,arg2,arg3); call第一个参数传对象,可以是null。参数以逗号分开进行传值,参数可以是任何类型。 apply(obj,...

    浅谈JavaScript中this的指向更改

    JS中this指向的更改 JavaScript 中 this 的指向问题 前面已经总结过,但在实际开中, 很多场景都需要改变 this 的...// 使用 call 方法改变调用函数执行上下文的 this 指向 var animal = '小猫'; var times = '15小时';

    js中this的绑定情况以及如何改变this的指向

    友情提示:this只有在执行的时候才能确认,定义时无法被确认 this的介绍: this是一个关键字,类似于...很多人误以为调用嵌套函数时,this会指向调用外层函数的上下文。如果你想访问这个外部函数的this值,需要将thi

    简单理解Python中的装饰器

    Python的装饰器可以实现在代码运行期间修改函数的上下文, 即可以定义函数在执行之前进行何种操作和函数执行后进行何种操作, 而函数本身并没有任何的改变。 首先, 我们先定义一个函数, 这个函数可以输出我的个人...

    简单上手Python中装饰器的使用

    Python的装饰器可以实现在代码运行期间修改函数的上下文, 即可以定义函数在执行之前进行何种操作和函数执行后进行何种操作, 而函数本身并没有任何的改变。 这个看起来很复杂, 实际上应用到了我之前说过的闭包的...

Global site tag (gtag.js) - Google Analytics