Introduction

After reading 《 You don't know JavaScript-- Scroll up 》 About China this After the introduction and in-depth chapters of , about this The direction of I use this article to summarize . And then I wondered if I could use this Knowledge about , Simulate it javascript It's more commonly used in call、apply、bind Methods? ?

So there is this article , I don't want to talk much nonsense !

Implicit loss

Due to the use of implicit loss in Simulation Implementation , So I'd like to introduce .

Implicit loss is a common this Binding problem , Refer to : Functions that are implicitly bound lose bound objects , And eventually apply to the default binding . Talk is talk : It was an implicit binding (obj.xxx this Point to obj) In the end, the default binding is applied (this Point to global object ).

Common cases of implicit loss 1: reference

var a = 'window'
function foo() {
console.log(this.a)
}
var obj = {
a: 'obj',
foo: foo
} obj.foo() // 'obj' here this => obj
var lose = obj.foo
lose() // 'window' here this => window

Common cases of implicit loss 2: Passed in as a callback function

var a = 'window'
function foo() {
console.log(this.a)
}
var obj = {
a: 'obj',
foo: foo
} function lose(callback) {
callback()
} lose(obj.foo) // 'window' here this => window // ================ Split line ===============
var t = 'window'
function bar() {
console.log(this.t)
} setTimeout(bar, 1000) // 'window'

For this, I conclude that ( I don't know right or wrong ): After excluding explicit binding , No matter how you do value passing , As long as it ends up being called without any modification , Then it applies to the default binding

Further get the key principle of the whole implementation : No matter how you do value passing , The way it's finally called determines this The direction of

Hard binding

The intuitive description of hard binding is : Once a function is explicitly specified this And then no matter how you call it later , its this The direction of will never be changed again

The implementation of hard binding solves the problem of implicit loss , bind The implementation of functions is based on the principle of hard binding

// Solve implicit loss 
var a = 'window'
function foo() {
console.log(this.a)
}
var obj = {
a: 'obj',
foo: foo
} function lose(callback) {
callback()
} lose(obj.foo) // 'window' var fixTheProblem = obj.foo.bind(obj)
lose(fixTheProblem) // 'obj'

Implementation and principle analysis

Simulation Implementation call

// Simulation Implementation call
Function.prototype._call = function ($this, ...parms) { // ...parms Now it's rest Operator , Used to receive all incoming arguments and return an array containing them
/*
this Will point to the call _call The function object of the method this It must be a function
** This step is crucial ** => Then temporarily store the object to our designated $this(context) In the object
*/
$this['caller'] = this
//$this['caller'](...parms) // This writing will be clearer than the one above
$this.caller(...parms) // ...parms Now it's spread Operator , Used to deconstruct elements in an array to caller Functions pass in arguments
/*
For the sake of clarity , Use the following more explicit way of writing instead of commenting out
1. $this.caller It's about us changing this Point to the original function
2. But because it's now $this.caller call , The rules of implicit binding are applied
3. therefore this Success points to $this
*/
delete $this['caller'] // This is a temporary property and cannot destroy the original structure of the artificially bound object , So it needs to be deleted after use
}

Simulation Implementation apply

// Simulation Implementation apply ** And _call The implementation of is almost the same , The main difference is only in the method of parameter transmission / On type **
Function.prototype._apply = function ($this, parmsArr) { // According to the original apply The second parameter passes in an array
$this['caller'] = this
$this['caller'](...parmsArr) // ...parmsArr Now it's spread Operator , Used to deconstruct elements in an array to caller Functions pass in arguments
delete $this['caller']
}

since _call And _apply The previous similarity ( Coupling degree ) So high , Then we can further study them ( The same code for ) To withdraw

function interface4CallAndApply(caller, $this, parmsOrParmArr) {
$this['caller'] = caller
$this['caller'](...parmsOrParmArr)
delete $this['caller']
} Function.prototype._call = function ($this, ...parms) {
var funcCaller = this
interface4CallAndApply(funcCaller, $this, parms)
} Function.prototype._apply = function ($this, parmsArr) {
var funcCaller = this
interface4CallAndApply(funcCaller, $this, parmsArr)
}

One that I think can be better demonstrated _call and _apply Examples of implementation principles

var myName = 'window'
var obj = {
myName: 'Fitz',
sayName() {
console.log(this.myName)
}
} var foo = obj.sayName var bar = {
myName: 'bar',
foo
} bar.foo()

Simulation Implementation bind

// Use the principle of hard binding to simulate the implementation bind
Function.prototype._bind = function ($this, ...parms) {
$bindCaller = this // Save the call _bind Object of function Be careful : The object is a function
// According to the original bind The return value of the function : It's a function
return function () { // use rest Operator substitution arguments To collect incoming arguments
return $bindCaller._apply($this, parms)
}
}

An example of how hard binding works

function hardBind(fn) {
var caller = this
var parms = [].slice.call(arguments, 1)
return function bound() {
parms = [...parms, ...arguments]
fn.apply(caller, parms) // apply You can accept a pseudo array instead of an array
}
} var myName = 'window'
function foo() {
console.log(this.myName)
}
var obj = {
myName: 'obj',
foo: foo,
hardBind: hardBind
} // Under normal circumstances
foo() // 'window'
obj.foo() // 'obj' var hb = hardBind(foo)
// You can see that once hard bound, no matter how it is called in the end, it can't be changed this Point to
hb() // 'window'
obj.hb = hb // to obj Add this method to test
obj.hb() // 'window' // Let's make an impression
var hb2 = obj.hardBind(foo)
hb2() // 'obj' // This call this It should have pointed to window

Overall implementation ( Pure version / No comment )

function interface4CallAndApply(caller, $this, parmsOrParmArr) {
$this['caller'] = caller
$this['caller'](...parmsOrParmArr)
delete $this['caller']
} Function.prototype._call = function ($this, ...parms) {
var funcCaller = this
interface4CallAndApply(funcCaller, $this, parms)
} Function.prototype._apply = function ($this, parmsArr) {
var funcCaller = this
interface4CallAndApply(funcCaller, $this, parmsArr)
} Function.prototype._bind = function ($this, ...parms) {
$bindCaller = this
return function () {
return $bindCaller._apply($this, parms)
}
} // ============ test ===============
var foo = {
name: 'foo',
sayHello: function (a, b) {
console.log(`hello, get the parms => ${a} and ${b}`)
}
} var bar = {
name: 'bar'
} foo.sayHello._call(bar, 'Fitz', 'smart')
foo.sayHello._apply(bar, ['Fitz', 'smart']) var baz = foo.sayHello._bind(bar, 'Fitz', 'smart')
baz() var testHardBind = foo.sayHello._bind(bar, 'hard', 'bind')
testHardBind._call(Object.create(null)) // hello, get the parms => hard and bind test _bind Hard binding of

At the end

I'm just a little white who is learning the front end , If there is something wrong, please correct it

If you feel inspired or helpful , Please leave a message or pay attention to me , Thank you very much! !

Simple simulation implementation javascript Medium call、apply、bind More articles on methods

  1. javascript Medium call(),apply(),bind() Differences in methods

    I've been confused before , Can't remember call(),apply(),bind() The difference between . Don't know how to use , Always in a state of ignorance . Until one day, I was asked about the difference between the three methods , So I think it's necessary to summarize . If there is something not comprehensive , Subsequent to ...

  2. Explain profound theories in simple language : understand JavaScript Medium call,apply,bind The difference between

      stay javascript And this Key words in the article , I talked about the following , Do a simple review :         1.this The meaning of object refers to the properties and methods in the current object .       2.this The variable direction ...

  3. Don't really think JavaScript in func.call/apply/bind It's omnipotent !

    Ever since I learned call/apply/bind After these three methods, I have been able to use them in all kinds of occasions, and I haven't stepped on any pits yet , How to use it? ? To put it bluntly, my own object doesn't have a certain method, but others have , I can go through call/apply/bind Go to ...

  4. elementary analysis JavaScript Medium Function.prototype.bind() Method

    Function.prototype.bind() Method bind() Method is used to bind a function to an object ,bind() Method creates a function , Function body this The value of the object is bound to the passed in bind() function ...

  5. JavaScript Medium Function.prototype.bind() Method

    Reprinted from :https://www.cnblogs.com/zztt/p/4122352.html Function.prototype.bind() Method bind() The main purpose of the method is to bind a function to a ...

  6. Javascript in call,apply,bind Detailed explanation and summary of the method

    stay javascript And this Keyword details In the article , I talked about the following , Do a simple review : 1.this The meaning of object refers to the properties and methods in the current object . 2.this The variability of pointing . When in global scope ,thi ...

  7. Javascript in call,apply,bind The difference between

    One . Explore call Methods the principle Function.prototype.call = function(obj) { // 1. Give Way fn Medium this Point to obj // eval(this.toString().r ...

  8. JavaScript in call,apply,bind Differences in methods

    call,apply,bind Methods are generally used to specify this Environment . var a = { user:"hahaha", fn:function(){ console.log(this.u ...

  9. JavaScript in call、apply Personal understanding

    JavaScript in call.apply Personal understanding In a word, it is popular to say :call.apply It's about change this The state of being }; } function personInfo(name,age){ t ...

  10. JavaScript Study (2)call&apply&bind&eval usage

    javascript Study (2)call&apply&bind&eval usage stay javascript There are several particularly useful functions in , It's convenient for us to realize all kinds of tricks . among ,call.bi ...

Random recommendation

  1. Progress bar ProgressDialog

    1. design sketch public void click(View view) { final ProgressDialog pdDialog = new ProgressDialog(this); // Set up the logo ...

  2. Create and use Web API

    I did an exercise today , Achieve separate Web API project. It used to be just ASP.NET MVC project Internal creation . Create a Web API project, Please refer to the following steps : Click on OK after , There's another ...

  3. Linux Tips no crontab for root Solutions for

    Linux Tips no crontab for root Solutions for install crontab:yum install crontabs explain :/sbin/service crond start // Start the service /s ...

  4. One c++ Script command system

    The project hopes to achieve some plot animation , Like character movement , The camera changes , Line presentation, etc . The plot animation needs to be modified and adjusted at any time , It can't be written dead in code . After thinking about it, I think we need to do a simple DSL To customize the script , Plan to write commands in sequence in the script , Then I ...

  5. easyui Source translation 1.32--Messager( Message window )

    Preface Use $.messager.defaults Override the default object . Download the plug-in translation source code The message window provides different message box styles , contain alert( Warning box ), confirm( Confirmation box ), prompt( Prompt box ), p ...

  6. 【 primary 】Redis Basic operation

    Redis Basic operation Traversal operation Pub-Sub server Lua Script Redis These operations in are case insensitive . In addition to specific operations for specific types . There are other operations . Traversal operation SCAN cursor [ ...

  7. Hust 1231 Coin

    Topic link The question : Bright and bright N A defective coin , Being flawed means the probability of flipping a coin face up It's not equal to The upside down probability That is, probability is not equal to 0.5. Now let's throw it once N A coin , There happens to be K Two coins face up , Then he wanted to throw it again ...

  8. 【 turn 】NSString / NSData / char* Conversion between types

    original text :http://www.cnblogs.com/pengyingh/articles/2341880.html NSString convert to NSData object NSData* xmlData = [ ...

  9. git Introduction to installation and use

    Install... From source Some people think that installing from the source code Git More practical , Because you can get the latest version . Binary installers tend to have some lag , Of course in recent years Git It's mature , The difference is no longer significant . If you want to install from source Git, Need to install Gi ...

  10. bzoj 1857: [Scoi2010] Conveyor belt Three points

    Topic link 1857: [Scoi2010] Conveyor belt Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 934  Solved: 501[Submit][Stat ...