Javascript Notes


Posted by on August 9, 2018

Index Dump function script How to use Call, Apply, Bind Promise


Dump function script

dump.js:

function func1(){
  console.log("func1!!");
}
console.log(func1.toString());

If you know nodejs, you can use node to do test as below.

node dump.js

How to use Call, Apply, Bind


Call and apply are the other ways to call function. The first parameter will replace this, and the difference between call and apply is the rest parameters. Call uses normal parameter input, and apply uses the array-based parameter input.

Normal function call:

Example:

var obj={
  x:5,
  z:'zzz',
  func1:function(){
    console.log('this.x: '+this.x+', this.y: '+this.y+', this.z: '+this.z+', arguments: '+JSON.stringify(arguments));
  }
}
obj.func1();

Output:

this.x: 5, this.y: undefined, this.z: zzz, arguments: {}

Use `call` to call function:

Example:

var obj={
  x:5,
  z:'zzz',
  func1:function(){
    console.log('this.x: '+this.x+', this.y: '+this.y+', this.z: '+this.z+', arguments: '+JSON.stringify(arguments));
  }
}
obj.func1.call({x:10,y:5}, "argv1", "argv2");

Output:

this.x: 10, this.y: 5, this.z: undefined, arguments: {"0":"argv1","1":"argv2"}

Use `apply` to call function:

Example:

var obj={
  x:5,
  z:'zzz',
  func1:function(){
    console.log('this.x: '+this.x+', this.y: '+this.y+', this.z: '+this.z+', arguments: '+JSON.stringify(arguments));
  }
}
var args=[];
args.push("argv1");
args.push("argv2");
obj.func1.apply({x:10,y:5}, args);

Output:

this.x: 10, this.y: 5, this.z: undefined, arguments: {"0":"argv1","1":"argv2"}


Promise
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

/**
 * Check if a value is a Promise and, if it is,
 * return the `then` method of that promise.
 *
 * @param {Promise|Any} value
 * @return {Function|Null}
 */
function getThen(value) {
  var t = typeof value;
  if (value && (t === 'object' || t === 'function')) {
    var then = value.then;
    if (typeof then === 'function') {
      return then;
    }
  }
  return null;
}

/**
 * Take a potentially misbehaving resolver function and make sure
 * onFulfilled and onRejected are only called once.
 *
 * Makes no guarantees about asynchrony.
 *
 * @param {Function} fn A resolver function that may not be trusted
 * @param {Function} onFulfilled
 * @param {Function} onRejected
 */
function doResolve(fn, onFulfilled, onRejected) {
  var done = false;
  try {
    fn(function (value) {
      if (done) return
      done = true
      onFulfilled(value)
    }, function (reason) {
      if (done) return
      done = true
      onRejected(reason)
    })
  } catch (ex) {
    if (done) return
    done = true
    onRejected(ex)
  }
}

function Promise(fn) {
  // store state which can be PENDING, FULFILLED or REJECTED
  var state = PENDING;

  // store value once FULFILLED or REJECTED
  var value = null;

  // store sucess & failure handlers
  var handlers = [];

  function fulfill(result) {
    state = FULFILLED;
    value = result;
    handlers.forEach(handle);
    handlers = null;
  }

  function reject(error) {
    state = REJECTED;
    value = error;
    handlers.forEach(handle);
    handlers = null;
  }

  function resolve(result) {
    try {
      var then = getThen(result);
      if (then) {
        doResolve(then.bind(result), resolve, reject)
        return
      }
      fulfill(result);
    } catch (e) {
      reject(e);
    }
  }

  function handle(handler) {
    if (state === PENDING) {
      handlers.push(handler);
    } else {
      if (state === FULFILLED &&
        typeof handler.onFulfilled === 'function') {
        handler.onFulfilled(value);
      }
      if (state === REJECTED &&
        typeof handler.onRejected === 'function') {
        handler.onRejected(value);
      }
    }
  }

  this.done = function (onFulfilled, onRejected) {
    // ensure we are always asynchronous
    setTimeout(function () {
      handle({
        onFulfilled: onFulfilled,
        onRejected: onRejected
      });
    }, 0);
  }

  this.then = function (onFulfilled, onRejected) {
    var self = this;
    return new Promise(function (resolve, reject) {
      return self.done(function (result) {
        if (typeof onFulfilled === 'function') {
          try {
            return resolve(onFulfilled(result));
          } catch (ex) {
            return reject(ex);
          }
        } else {
          return resolve(result);
        }
      }, function (error) {
        if (typeof onRejected === 'function') {
          try {
            return resolve(onRejected(error));
          } catch (ex) {
            return reject(ex);
          }
        } else {
          return reject(error);
        }
      });
    });
  }

  doResolve(fn, resolve, reject);
}

console.log('before p1');
var p1=new Promise(function(resolve, reject){
  setTimeout(function(){
    resolve(3); 
  }, 5000);
});
p1.then(function(){
  console.log('ok!!');
}, function(){
  console.log('fail!!');
});
p1.done(function(){
  console.log('done!!');
});
console.log('after p1');

To be continued…

本站總訪問量訪客