js高级用法----手写js原生方法
作者:互联网
1、call 方法
/** * _call * * @param { context } context * @param { arguments } arguments */ Function.prototype._call = function(context) { // 如果没有传或传的值为空对象 context指向window context = context || window let fn = Symbol(context) context[fn] = this //给context添加一个方法 指向this // 处理参数 去除第一个参数this 其它传入fn函数 let args = [...arguments].slice(1) //[...xxx]把类数组变成数组,arguments为啥不是数组自行搜索 slice返回一个新数组 context[fn](...args) //执行fn delete context[fn] //删除方法 } var obj = { name: 'Bob', age: '18', fn() { console.log(`My name is ${this.name}, my age is ${this.age}`) } } var dog = { name: 'Snoopy', age: 3 } obj.fn.call(dog,'daddata','ttt','yuyuyuuy') // My name is Snoby, my age is 3 obj.fn._call(dog,'daddata','ttt','yuyuyuuy') // My name is Snoby, my age is 3
2、 apply 方法
Function.prototype._apply = function(context) { // 如果没有传或传的值为空对象 context指向window context = context || window let fn = Symbol(context) context[fn] = this let arg = [...arguments].slice(1) context[fn](arg) //执行fn delete context[fn] //删除方法 }
3、bind方法
/** * _bind * * @param {*} context */ Function.prototype._bind = function (context) { //返回一个绑定this的函数,我们需要在此保存this let self = this // 可以支持柯里化传参,保存参数 let arg = [...arguments].slice(1) // 返回一个函数 return function () { //同样因为支持柯里化形式传参我们需要再次获取存储参数 let newArg = [...arguments] // 返回函数绑定this,传入两次保存的参数 //考虑返回函数有返回值做了return return self.apply(context, arg.concat(newArg)) } }
4、promise方法
function MyPromise(exceptor) { let _this = this; _this.reason = ''; _this.value = ''; _this.resolveFnArr = []; _this.rejectFnArr = []; _this.status = 'pending'; function resolve(val) { if (_this.status === 'pending') { _this.value = val; _this.status = 'fulfiled'; _this.resolveFnArr.forEach(fn => fn()) } } function reject(reason) { if (_this.status === 'pending') { _this.reason = reason; _this.status = 'reject'; _this.rejectFnArr.forEach(fn => fn()) } } try { exceptor(resolve, reject); } catch (error) { reject(); } } MyPromise.prototype.then = function(resolve, reject) { let _this = this; if (_this.status === 'fulfiled') { resolve(_this.value); } if (_this.status === 'reject') { reject(_this.reason); } if (_this.status === 'pending') { _this.resolveFnArr.push(() => {resolve(_this.value)}) _this.rejectFnArr.push(() => {reject(_this.reason)}) } }
5、全面的promise写法
(function(window,undefined){ // resolve 和 reject 最终都会调用该函数 var final = function(status,value){ var _this = this, fn, status; if(_this._status !== 'PENDING') return; // 所以的执行都是异步调用,保证then是先执行的 setTimeout(function(){ _this._status = status; status = _this._status === 'FULFILLED' queue = _this[status ? '_resolves' : '_rejects']; while(fn = queue.shift()) { value = fn.call(_this, value) || value; } _this[status ? '_value' : '_reason'] = value; _this['_resolves'] = _this['_rejects'] = undefined; }); } //参数是一个函数,内部提供两个函数作为该函数的参数,分别是resolve 和 reject var MyPromise = function(resolver){ if (!(typeof resolver === 'function' )) throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); //如果不是promise实例,就new一个 if(!(this instanceof MyPromise)) return new MyPromise(resolver); var _this = this; _this._value; _this._reason; _this._status = 'PENDING'; //存储状态 _this._resolves = []; _this._rejects = []; // var resolve = function(value) { //由於apply參數是數組 final.apply(_this,['FULFILLED'].concat([value])); } var reject = function(reason){ final.apply(_this,['REJECTED'].concat([reason])); } resolver(resolve,reject); } MyPromise.prototype.then = function(onFulfilled,onRejected){ var _this = this; // 每次返回一个promise,保证是可thenable的 return new MyPromise(function(resolve,reject){ function handle(value) { // 這一步很關鍵,只有這樣才可以將值傳遞給下一個resolve var ret = typeof onFulfilled === 'function' && onFulfilled(value) || value; //判断是不是promise 对象 if (ret && typeof ret ['then'] == 'function') { ret.then(function(value) { resolve(value); }, function(reason) { reject(reason); }); } else { resolve(ret); } } function errback(reason){ reason = typeof onRejected === 'function' && onRejected(reason) || reason; reject(reason); } if(_this._status === 'PENDING'){ _this._resolves.push(handle); _this._rejects.push(errback); }else if(_this._status === FULFILLED){ // 状态改变后的then操作,立刻执行 callback(_this._value); }else if(_this._status === REJECTED){ errback(_this._reason); } }); } MyPromise.prototype.catch = function(onRejected){ return this.then(undefined, onRejected) } MyPromise.prototype.delay = function(ms,value){ return this.then(function(ori){ return MyPromise.delay(ms,value || ori); }) } MyPromise.delay = function(ms,value){ return new MyPromise(function(resolve,reject){ setTimeout(function(){ resolve(value); console.log('1'); },ms); }) } MyPromise.resolve = function(arg){ return new MyPromise(function(resolve,reject){ resolve(arg) }) } MyPromise.reject = function(arg){ return MyPromise(function(resolve,reject){ reject(arg) }) } MyPromise.all = function(promises){ if (!Array.isArray(promises)) { throw new TypeError('You must pass an array to all.'); } return MyPromise(function(resolve,reject){ var i = 0, result = [], len = promises.length, count = len //这里与race中的函数相比,多了一层嵌套,要传入index function resolver(index) { return function(value) { resolveAll(index, value); }; } function rejecter(reason){ reject(reason); } function resolveAll(index,value){ result[index] = value; if( --count == 0){ resolve(result) } } for (; i < len; i++) { promises[i].then(resolver(i),rejecter); } }); } MyPromise.race = function(promises){ if (!Array.isArray(promises)) { throw new TypeError('You must pass an array to race.'); } return MyPromise(function(resolve,reject){ var i = 0, len = promises.length; function resolver(value) { resolve(value); } function rejecter(reason){ reject(reason); } for (; i < len; i++) { promises[i].then(resolver,rejecter); } }); } window.MyPromise = MyPromise; })(window);
标签:function,MyPromise,resolve,value,js,----,reason,reject,手写 来源: https://www.cnblogs.com/zhangycun/p/14010488.html