foreword

There was an interview before. The interviewer asked about the knowledge points related to promises, and then I answered. He asked how to realize the chain of promises? I didn't respond at the time. The interviewer was very patient and said that jquery is also chained. Have you seen the source code of jquery? How is its chain written? I still don’t know. I failed the interview later. This knowledge point is often recalled by me. Now I have the time to write about it.

text

The answer is: return this

Let's start with an example:

 var person = {
    name: 'johan',
    age: 28,
    sayName: function() {
        console.log('my name is' + this.name)
    },
    sayAge: function() {
        console.log('my age is ' + this.age)
    }
}

Name an object, it has two methods, sayName and sayAge, what if I want to represent it like this person.sayName().sayAge() ? How to do it, return this in the methods sayName and sayAge, ie

 var person = {
    name: 'johan',
    age: 28,
    sayName: function() {
        console.log('my name is' + this.name)
        return this;
    },
    sayAge: function() {
        console.log('my age is ' + this.age)
        return this;
    }
}

This means that after calling the methods sayName and sayAge, it returns to the caller, that is, in the example person.sayName() , person calls sayName, and the return value after the call is still person. So it can continue to chain sayAge because it still represents person

Chaining in Promises

Promise itself has no chain, but the then in the instance object of Promise has chain

 function MyPromise(executor) {
    
}

MyPromise.prototype.then = function (onFulfilled, onRejected) {
    return new Promise((resolve, reject) => {
        ...
    })
}

When you use Promises, you generally use them like this:

 let promise = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000)
})
promise.then(() => {
    console.log('1s后显示')
})

If chained

 promise.then(() => {
    console.log('1s后显示,第一个')
}).then(() => {
    console.log('1s后显示,第二个')
})

So obviously, every call to then returns an instance object ( return new Promise )

Chaining in Jquery

There is too much content in the source code, take the code in core.js as an example

 jQuery.fn = jQuery.prototype = {

    // The current version of jQuery being used
    jquery: version,

    constructor: jQuery,

    // The default length of a jQuery object is 0
    length: 0,

    toArray: function() {
        return slice.call( this );
    },

    // Get the Nth element in the matched element set OR
    // Get the whole matched element set as a clean array
    get: function( num ) {

        // Return all the elements in a clean array
        if ( num == null ) {
            return slice.call( this );
        }

        // Return just the one element from the set
        return num < 0 ? this[ num + this.length ] : this[ num ];
    },

    // Take an array of elements and push it onto the stack
    // (returning the new matched element set)
    pushStack: function( elems ) {

        // Build a new jQuery matched element set
        var ret = jQuery.merge( this.constructor(), elems );

        // Add the old object onto the stack (as a reference)
        ret.prevObject = this;

        // Return the newly-formed element set
        return ret;
    },

    // Execute a callback for every element in the matched set.
    each: function( callback ) {
        return jQuery.each( this, callback );
    },

    map: function( callback ) {
        return this.pushStack( jQuery.map( this, function( elem, i ) {
            return callback.call( elem, i, elem );
        } ) );
    },

    slice: function() {
        return this.pushStack( slice.apply( this, arguments ) );
    },

    first: function() {
        return this.eq( 0 );
    },

    last: function() {
        return this.eq( -1 );
    },

    even: function() {
        return this.pushStack( jQuery.grep( this, function( _elem, i ) {
            return ( i + 1 ) % 2;
        } ) );
    },

    odd: function() {
        return this.pushStack( jQuery.grep( this, function( _elem, i ) {
            return i % 2;
        } ) );
    },

    eq: function( i ) {
        var len = this.length,
            j = +i + ( i < 0 ? len : 0 );
        return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
    },

    end: function() {
        return this.prevObject || this.constructor();
    }
};

We don't have to look at all of them, but look at the method, is it similar to the return this

So the chain is not scary, the scary thing is that you will persuade yourself to quit at every turn.

This article participated in the SegmentFault Sifu essay "How to "anti-kill" the interviewer?" , you are welcome to join.

山头人汉波
394 声望555 粉丝