添加事件时调用的方法的this又想指向其他对象

1.应用案例:

var Mouse = function () {

// Look! no that = this!

this.position = [0, 0];

if (document.addEventListener) {

document.addEventListener(‘mousemove‘, ?);   //this.move?

} else if (document.attachEvent) {

document.attachEvent("onmousemove", ?);     //this.move?怎么放进去

}

};

Mouse.prototype.move = function (arg1,arg2,event) {

event = window.event || event;

var x = event.pageX || event.offsetX,

y = event.pageY || event.offsetY;

this.position = position = [x, y];

this.log(arg1,arg2);

};

Mouse.prototype.log = function (arg1, arg2) {

console.log(arg1+","+arg2);

console.log(this.position);

};

new Mouse();

上面你知道‘?‘号那里要干嘛了吗?我想给document的mousemove绑定我的move方法,但是遇到难题了,这样的话,Mouse.prototype.move

里的this就不会指向Mouse的对象,相信大家经常碰到这种问题.也许你早知道了怎么解决,但是有更快更简单的方法吗?答案是:

Function.prototype.bind()这个神奇的玩意,但是ie6 7 8都不支持,一般现代浏览器都支持了,我们接下来要做的就是模仿他,

这么好的方法当然要模仿它,怎么模仿见下面nothing的原创方法

(function () {

var proxy = function (fn, target) {

var proxy = function () {

if (2 < arguments.length) { //存在被代理的函数有参数的时候

var privateArgs = Array.prototype.slice.call(arguments, 2);

//从第二个开始取出来,[this,绑定的对象,参数列表]

return function () {

var args = Array.prototype.slice.call(arguments);

-->这里的arguments与外面的不是同一个,这个是被代理的函数内部的arguments对象,

比如这里的move函数的  arguments[0]=[object Event]就是这个事件内部的e参数

Array.prototype.unshift.apply(args, privateArgs);

-->这里在加上传进来的参数,就实现了,和原生bind一样的参数形式

//->而且这里是把私有的参数放到前面的比如a=new Mouse();a.move(1,2);

//如果这个move方法没有参数,意思就是prototype.move=fn(){arguments} ,

//而我传进来了参数,参数的arguments.length=3,

//arguments[0]=1,arguments[1]=2,arguments[2]=[object event].

return fn.apply(target, args);

}

//这里之所以搞复杂了,是因为,在被代理的函数可以直接访问arguments,比如我不给被代理的函数传参数,而直接使用

//这样这个arguments就会包含与原生Function.prototype.bind的arguments一样的对象,

//这里代码深奥,是因为你没理解这里原生的bind里面的arguments是什么,知道了,就知道为什么绑定我自己的arguments

//做这么多,主要目的就是使你被代理的函数内部的arguments与function.prototype.bind里的arguments对象包含的东西一致

}

return function () {

return fn.apply(target, arguments);

}

}

return proxy.apply(null, arguments);

};

/*支持原生的使用原生的*/

Function.prototype.bind = Function.prototype.bind ||

function (target) {                   //这里的this指代要被代理的函数

if (1 < arguments.length) {

var args = Array.prototype.slice.call(arguments, 1);  //取出参数列表

args.unshift(this, target);  //这个args最终变成了[this,绑定的对象,参数列表]

return proxy.apply(null, args);

-->估计大家会跟17楼犯一样的错误,这里之所以这么复杂的操作arguments对象,只是为了能保证传进proxy函数中,保证arguments对象不失效

}

return proxy(this, target);

};

})();

以上代码为什么我要一直return回来代理,因为这样你才能这样调用this.move.bind(this,1,2)()然后这里会立即执行函数!

有了以上代码,我们就可以轻松的实现了"?"号这里要写什么代码了,^_^,简单吧

if (document.addEventListener) {

document.addEventListener(‘mousemove‘, this.move.bind(this,1,2));

} else if (document.attachEvent) {

document.attachEvent("onmousemove", this.move.bind(this,1,2));

}

是不是以后凡是碰到要添加事件,然后调用的方法的this又想指向其他对象,这样是不是很简单呢..

看到大家对以上代码有点难理解,来个简单点得

var a = function () {

console.log(arguments[0]);   //1

console.log(arguments[1]);   //2

console.log(this.key1);

//这样绑定参数的话,我的参数列出来才能和原生的bind一样,就这么简单,

};

var b = {

key1: "value1"

};

a.bind(b, 1, 2)();

反驳17楼同学的代码错误,我想这是很多人会犯的错误,代码如下

Function.prototype.bind = function (target) {

var self = this;

return function () {

return self.apply(target, arguments); //这里的arguments根本传不进来

}

}

var a = function () {

console.log(arguments.length);  //这样bind的话,arguments参数失效

//arguments.length=0.

console.log(this.key1);

};

var b = {

key1: "value1"

};

a.bind(b, [1, 2], 3)();    //从这里可以看出,期望的arguments.length=2

//这也是我为什么苦口婆心的操作arguments参数

//我知道这里大部分人都会觉得对的,但是你错了,17楼的同学你还得在思考下

不带注释的源码,

(function () {

var proxy = function (fn, target) {

var proxy = function () {

if (2 < arguments.length) {

var privateArgs = Array.prototype.slice.call(arguments, 2);

return function () {

var args = Array.prototype.slice.call(arguments);

Array.prototype.unshift.apply(args,privateArgs);

return fn.apply(target, args);

}

}

return function () {

return fn.apply(target, arguments);

}

}

return proxy.apply(null, arguments);

};

/*支持原生的使用原生的*/

Function.prototype.bind = Function.prototype.bind ||

function (target) {

if (1 < arguments.length) {

var args = Array.prototype.slice.call(arguments, 1);

args.unshift(this, target);

return proxy.apply(null, args);

}

return proxy(this, target);

};

})();

时间: 2024-09-30 06:58:05

添加事件时调用的方法的this又想指向其他对象的相关文章

angularjs 动态表单, 原生事件中调用angular方法

https://www.cnblogs.com/wancy86/p/7834067.html 1. 原生事件中调用angular方法, 比如 input的onChange事件想调用angular里面定义的方法 - onChange="angular.element(this).scope().uploadPhoto(this)" <div class="col-md-2"> <input onChange="angular.element

ASP.NET jQuery 事件里调用后台方法

利用js 调用后台写的方法 1 <script src="js/jquery-1.7.1.min.js"></script> 2 2 <script> 3 3 $(function () { 4 4 $(".btn").click(function () { 5 5 $("#txtname").val('<%=Session["Name"]%>'); 6 6 $("#t

JS闭包导致循环给按钮添加事件时总是执行最后一个

加入如下脚本代码: <script> var list_obj = document.getElementsByTagName('li'); for (var i = 0; i <= list_obj.length; i++) { list_obj[i].onclick = function() { alert(i); } } </script> 运行后,奇怪的发现无论点击那个li标签,alert出的都是最后一个的内容,5 下面做下分析:因为在for循环里面指定给list_o

js页面加载时调用函数方法

方法一:在html的body中加入onload=""事件 <body onload='queryServer()'> </body> 方法二:jquery 中:$(function(){}) //方法体里面写调用方法 <!-- 全局js --><script src="../js/jquery.min.js?v=2.1.4"></script> <script type="text/java

ie下,jquery为动态添加的节点添加事件,用live

jQuery向动态生成的内容添加事件响应 jQuery live() 方法详解 [收藏] 发布时间:2013-07-24 点击次数:176 来源:www.daimajiayuan.com jQuery live() 方法是给所有匹配的元素附加一个事件处理函数,即使这个元素是以后通过append,prepend,after等事件生成后的内容也依然有效. 这个方法可以看做是 .bind() 方法的一个变体.使用 .bind() 时,选择器匹配的元素会附加一个事件处理函数,而以后再添加的元素则不会有.

解决JavaScript中批量添加事件的问题

这是JavaScript中一个老生常谈的问题,也是初学者较难理解的问题.当给一系列元素添加事件时,常常会出现一些我们不希望出现的问题.例如以下代码: //给li元素批量添加click事件 window.onload = function(){ var lists = document.getElementsByTagName("li"); for(var i=0;i<lists.length;i++){ lists[i].onclick = function(){ alert(i

javascript面向对象--观察者模式(为对象添加事件监听功能)

正文开始之前,有这么一个需求: >背景:宁静的夜晚,一天晚上,狗蛋(主人)睡得正香,侠盗高飞(小偷)突然造访. >事件:高飞正准备下手的时候,不料被旺财(狗)发现了,于是旺财叫了起来,狗蛋醒了,高飞逃走了. 分析需求后,可以发现有三个对象: 高飞(小偷) 旺财(狗) 狗蛋(主人) 创建对象的构造函数以及原型方法 //人的构造函数 function Person(name){ this.name=name; //首次创建实例时,为Person的原型添加共有的方法 if(!Person.proto

Spring AOP不拦截从对象内部调用的方法

拦截器的实现原理很简单,就是动态代理,实现AOP机制.当外部调用被拦截bean的拦截方法时,可以选择在拦截之前或者之后等条件执行拦截方法之外的逻辑,比如特殊权限验证,参数修正等操作. 但是最近在项目中要在一个事务中跨数据源进行操作.数据库跨源就不在这里说了,可以自行百度. 这里出现的问题就是,如果我们要拦截某个类的多个方法,且在该类的方法中使用this调用要拦截的方法时会导致拦截失败. 这样说有点抽象,看一个代码: package com.intsmaze.before; public clas

Spring AOP不拦截从对象内部调用的方法原因

拦截器的实现原理很简单,就是动态代理,实现AOP机制.当外部调用被拦截bean的拦截方法时,可以选择在拦截之前或者之后等条件执行拦截方法之外的逻辑,比如特殊权限验证,参数修正等操作. 但是最近在项目中要在一个事务中跨数据源进行操作.数据库跨源就不在这里说了,可以自行百度. 这里出现的问题就是,如果我们要拦截某个类的多个方法,且在该类的方法中使用this调用要拦截的方法时会导致拦截失败. 这样说有点抽象,看一个代码: package com.intsmaze.before; public clas