1. Application case:
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? How to put it in
}
};
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();
Do you know what the '?' number is for above? I want to bind my move method to mousemove of document, but I encountered a problem. In this case, Mouse.prototype.move
this will not point to the Mouse object. I believe everyone often encounters this problem. Maybe you already know how to solve it, but is there a faster and simpler way? The answer is:
Function.prototype.bind() It’s a magical thing, but it’s not supported by IE6, 7 or 8. Most modern browsers support it. The next thing we have to do is to imitate it.
Of course we have to imitate such a good method. How to imitate it is nothing’s original method below.
(function () {
var proxy = function (fn, target) {
var proxy = function () {
if (2 < arguments.length) { //When the proxy function has parameters
var privateArgs = Array.prototype. slice.call(arguments, 2);
//Take out the second one, [this, bound object, parameter list]
return function () {
var args = Array.prototype .slice.call(arguments);
-->The arguments here are not the same as those outside. This is the arguments object inside the proxy function.
For example, the arguments[0]= of the move function here. [object Event] is the e parameter inside this event
Array.prototype.unshift.apply(args, privateArgs);
-->gt; Add the uploaded parameters here and it will be implemented, just like the native bind The parameter form
//-> and here the private parameters are put in front, such as a=new Mouse();a.move(1,2);
//If this move method has no parameters , meaning prototype.move=fn(){arguments},
//I passed in the parameters, arguments.length=3,
//arguments[0]=1,arguments[1] =2,arguments[2]=[object event].
return fn.apply(target, args);
}
//The reason why it is complicated here is that in the function being proxied Arguments can be accessed directly. For example, I do not pass parameters to the proxy function, but directly use
//In this way, the arguments will contain the same object as the arguments of the native Function.prototype.bind,
//Here is the code It's profound because you don't understand what the arguments in the native bind here are. If you know it, you will know why I bind my own arguments
//The main purpose of doing so much is to make the arguments inside the function you are proxying Consistent with what the arguments object in function.prototype.bind contains
}
return function () {
return fn.apply(target, arguments);
}
}
return proxy.apply(null, arguments);
};
/*Support native and use native*/
Function.prototype.bind = Function.prototype.bind ||
function (target ) { //This here refers to the function to be proxied
if (1 < arguments.length) {
var args = Array.prototype.slice.call(arguments, 1); //Take out the parameters List
args.unshift(this, target); //This args eventually becomes [this, bound object, parameter list]
return proxy.apply(null, args);
-- If you directly proxy(args), trouble will come. args becomes a parameter of the proxy function, and an error will be reported.
In fact, the main task here is to separate tasks. The proxy only cares about how the proxy and parameters are passed to the proxy. If it is proxied There are no parameters, just direct;
return proxy(this, target)--> return fn.apply(target, arguments); This is the answer on the 17th floor
--> I guess everyone will make the same mistake as the 17th floor Same mistake. The reason why the arguments object is so complicated here is just to ensure that it is passed into the proxy function and that the arguments object does not expire
}
return proxy(this, target);
};
})();
Why do I have to keep returning the proxy in the above code? Because in this way you can call this.move.bind(this,1,2)() and then it will be immediately Execute the function!
With the above code, we can easily implement the code "?". What code should be written here? ^_^, it's simple
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));
}
Do you need to add events whenever you encounter them in the future, and then call The this of the method wants to point to other objects. Isn't this very simple?
Seeing that it is a bit difficult for everyone to understand the above code, let's make it simpler
var a = function () {
console.log(arguments[0]); //1
console.log(arguments[1]); //2
console.log(this.key1);
//If I bind parameters in this way, my parameters can be listed the same as the native bind, that's it Simple,
};
var b = {
key1: "value1"
};
a.bind(b, 1, 2)();
Rebutting the code error of the classmate on the 17th floor, I think this is a mistake that many people will make. The code is as follows
Function.prototype.bind = function (target) {
var self = this;
return function () {
return self.apply(target, arguments) ; //The arguments here cannot be passed in at all
}
}
var a = function () {
console.log(arguments.length); //If you bind like this, the arguments parameters will be invalid
//arguments.length=0.
console.log(this.key1);
};
var b = {
key1: "value1"
};
a.bind(b, [1, 2], 3)(); //It can be seen from here that the expected arguments.length=2
//This is why I painstakingly operate the arguments parameters
/ /I know that most people here will think it is right, but you are wrong. Students on the 17th floor, you still have to think about it
Source code without comments,
(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);
};
/*Support native use native*/
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);
};
})();
This article is a continuation of the previous article. I will talk about this A detailed example, if you haven’t seen it, click
to read the example first. This blog does not have time to make a gorgeous layout, only simple code, only for js code lovers
var Mouse = function () {
if (document.addEventListener) {
document. addEventListener('mousemove', this.move.bind(this,1,2,[3,4]));
} else if (document.attachEvent) {
document.attachEvent("onmousemove", this .move.bind(this,1,2,[3,4]));
}
};
Mouse.prototype.move = function () {
console.log(arguments[ arguments.length-1].clientX);
};
The output results of arguments here explain the above code very well. If you don’t understand, please combine it with the newly given examples to understand. .
var privateArgs = Array.prototype.slice.call( arguments, 2);
//Private parameters, representing the parameters of the agent, here representing 1,2,[3,4]
return function () {
var args = Array.prototype.slice .call(arguments);
//The parameters here represent the parameters of the delegate, such as e inside the event function
Array.prototype.unshift.apply(args, privateArgs);
// Here, the two parameters are merged together, and then the private parameters are first. The purpose is to be consistent with the original parameter order
return fn.apply(target, args);
//The merged parameters are here Including 1,2,[3,4] e is passed in and apply
}
Okay, when you get here, you will find a good js skill, that is, you don’t need to handle e=window.event||e directly, and you can directly use arguments[arguments.length-1] to be compatible with all browsers represented
The event e object saves a lot of code and thinking time.
The reason why I wrote this code is that I hope everyone can have a real understanding of js code and know the real charm of js. If it is really After reading this article, at least you know what arguments
is all about. This blog is extremely shabby, with only simple code, suitable for js code enthusiasts to learn.
In fact, the real charm of js does not end with this. With the above examples and explanations, I believe you should understand it almost. If you don’t know, you will know it after a few demos.
A js enthusiast will post some fresher codes from time to time for everyone to learn. This book The purpose of the blog is to learn the essence of js code together.