464 lines
11 KiB
JavaScript
464 lines
11 KiB
JavaScript
|
/*-----------------部分ES6的JS实现 start---------------*/
|
|||
|
|
|||
|
// ===============================
|
|||
|
// ========== Promise ============
|
|||
|
// ===============================
|
|||
|
;(function(nativePromise) {
|
|||
|
function _yes(val) {
|
|||
|
return val
|
|||
|
}
|
|||
|
|
|||
|
function _no(err) {
|
|||
|
throw err
|
|||
|
}
|
|||
|
|
|||
|
function done(callback) {
|
|||
|
return this.then(callback, _no)
|
|||
|
}
|
|||
|
|
|||
|
function fail(callback) {
|
|||
|
return this.then(_yes, callback)
|
|||
|
}
|
|||
|
|
|||
|
function defer() {
|
|||
|
var obj = {}
|
|||
|
obj.promise = new _Promise(function(yes, no) {
|
|||
|
obj.resolve = yes
|
|||
|
obj.reject = no
|
|||
|
})
|
|||
|
return obj
|
|||
|
}
|
|||
|
|
|||
|
//成功的回调
|
|||
|
function _resolve(obj, val) {
|
|||
|
if (obj._state !== 'pending') {
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
if (val && typeof val.then === 'function') {
|
|||
|
var method = val instanceof _Promise ? '_then' : 'then'
|
|||
|
val[method](
|
|||
|
function(v) {
|
|||
|
_transmit(obj, v, true)
|
|||
|
},
|
|||
|
function(v) {
|
|||
|
_transmit(obj, v, false)
|
|||
|
}
|
|||
|
)
|
|||
|
} else {
|
|||
|
_transmit(obj, val, true)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//失败的回调
|
|||
|
function _reject(obj, val) {
|
|||
|
if (obj._state !== 'pending') {
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
_transmit(obj, val, false)
|
|||
|
}
|
|||
|
|
|||
|
// 改变Promise的_fired值,并保持用户传参,触发所有回调
|
|||
|
function _transmit(obj, val, isResolved) {
|
|||
|
obj._fired = true
|
|||
|
obj._val = val
|
|||
|
obj._state = isResolved ? 'fulfilled' : 'rejected'
|
|||
|
|
|||
|
fireCallback(obj, function() {
|
|||
|
for (var i in obj.callback) {
|
|||
|
obj._fire(obj.callback[i].yes, obj.callback[i].no)
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function fireCallback(obj, callback) {
|
|||
|
var isAsync = false
|
|||
|
|
|||
|
if (typeof obj.async === 'boolean') {
|
|||
|
isAsync = obj.async
|
|||
|
} else {
|
|||
|
isAsync = obj.async = true
|
|||
|
}
|
|||
|
|
|||
|
if (isAsync) {
|
|||
|
setTimeout(callback, 0)
|
|||
|
} else {
|
|||
|
callback()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function _some(bool, iterable) {
|
|||
|
iterable = Array.isArray(iterable) ? iterable : []
|
|||
|
|
|||
|
var n = 0
|
|||
|
var res = []
|
|||
|
var end = false
|
|||
|
|
|||
|
return new _Promise(function(yes, no) {
|
|||
|
if (!iterable.length) no(res)
|
|||
|
|
|||
|
function loop(obj, idx) {
|
|||
|
obj.then(
|
|||
|
function(val) {
|
|||
|
if (!end) {
|
|||
|
res[idx] = val
|
|||
|
n++
|
|||
|
if (bool || n >= iterable.length) {
|
|||
|
yes(bool ? val : res)
|
|||
|
end = true
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
function(val) {
|
|||
|
end = true
|
|||
|
no(val)
|
|||
|
}
|
|||
|
)
|
|||
|
}
|
|||
|
|
|||
|
for (var i = 0, len = iterable.length; i < len; i++) {
|
|||
|
loop(iterable[i], i)
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
//---------------------------
|
|||
|
var _Promise = function(callback) {
|
|||
|
this.callback = []
|
|||
|
var _this = this
|
|||
|
|
|||
|
if (typeof this !== 'object') {
|
|||
|
throw new TypeError('Promises must be constructed via new')
|
|||
|
}
|
|||
|
|
|||
|
if (typeof callback !== 'function') {
|
|||
|
throw new TypeError('Argument must be a function')
|
|||
|
}
|
|||
|
|
|||
|
callback(
|
|||
|
function(val) {
|
|||
|
_resolve(_this, val)
|
|||
|
},
|
|||
|
function(val) {
|
|||
|
_reject(_this, val)
|
|||
|
}
|
|||
|
)
|
|||
|
}
|
|||
|
var self = {
|
|||
|
_state: 1,
|
|||
|
_fired: 1,
|
|||
|
_val: 1,
|
|||
|
callback: 1
|
|||
|
}
|
|||
|
|
|||
|
_Promise.prototype = {
|
|||
|
constructor: _Promise,
|
|||
|
_state: 'pending',
|
|||
|
_fired: false,
|
|||
|
_fire: function(yes, no) {
|
|||
|
if (this._state === 'rejected') {
|
|||
|
if (typeof no === 'function') no(this._val)
|
|||
|
else throw this._val
|
|||
|
} else {
|
|||
|
if (typeof yes === 'function') yes(this._val)
|
|||
|
}
|
|||
|
},
|
|||
|
_then: function(yes, no) {
|
|||
|
if (this._fired) {
|
|||
|
var _this = this
|
|||
|
fireCallback(_this, function() {
|
|||
|
_this._fire(yes, no)
|
|||
|
})
|
|||
|
} else {
|
|||
|
this.callback.push({ yes: yes, no: no })
|
|||
|
}
|
|||
|
},
|
|||
|
then: function(yes, no) {
|
|||
|
yes = typeof yes === 'function' ? yes : _yes
|
|||
|
no = typeof no === 'function' ? no : _no
|
|||
|
var _this = this
|
|||
|
var next = new _Promise(function(resolve, reject) {
|
|||
|
_this._then(
|
|||
|
function(val) {
|
|||
|
try {
|
|||
|
val = yes(val)
|
|||
|
} catch (err) {
|
|||
|
return reject(err)
|
|||
|
}
|
|||
|
resolve(val)
|
|||
|
},
|
|||
|
function(val) {
|
|||
|
try {
|
|||
|
val = no(val)
|
|||
|
} catch (err) {
|
|||
|
return reject(err)
|
|||
|
}
|
|||
|
resolve(val)
|
|||
|
}
|
|||
|
)
|
|||
|
})
|
|||
|
for (var i in _this) {
|
|||
|
if (!self[i]) next[i] = _this[i]
|
|||
|
}
|
|||
|
return next
|
|||
|
},
|
|||
|
done: done,
|
|||
|
catch: fail,
|
|||
|
fail: fail
|
|||
|
}
|
|||
|
|
|||
|
_Promise.all = function(arr) {
|
|||
|
return _some(false, arr)
|
|||
|
}
|
|||
|
|
|||
|
_Promise.race = function(arr) {
|
|||
|
return _some(true, arr)
|
|||
|
}
|
|||
|
|
|||
|
_Promise.defer = defer
|
|||
|
|
|||
|
_Promise.resolve = function(val) {
|
|||
|
var obj = this.defer()
|
|||
|
obj.resolve(val)
|
|||
|
return obj.promise
|
|||
|
}
|
|||
|
|
|||
|
_Promise.reject = function(val) {
|
|||
|
var obj = this.defer()
|
|||
|
obj.reject(val)
|
|||
|
return obj.promise
|
|||
|
}
|
|||
|
if (/native code/.test(nativePromise)) {
|
|||
|
nativePromise.prototype.done = done
|
|||
|
nativePromise.prototype.fail = fail
|
|||
|
if (!nativePromise.defer) {
|
|||
|
nativePromise.defer = defer
|
|||
|
}
|
|||
|
}
|
|||
|
window.Promise = nativePromise || _Promise
|
|||
|
})(window.Promise)
|
|||
|
|
|||
|
if (!Object.assign) {
|
|||
|
Object.defineProperty(Object, 'assign', {
|
|||
|
enumerable: false,
|
|||
|
value: function(target, first) {
|
|||
|
'use strict'
|
|||
|
if (target === undefined || target === null)
|
|||
|
throw new TypeError('Can not convert first argument to object')
|
|||
|
|
|||
|
var to = Object(target)
|
|||
|
for (var i = 0, len = arguments.length; i < len; i++) {
|
|||
|
var next = arguments[i]
|
|||
|
if (next === undefined || next === null) continue
|
|||
|
|
|||
|
var keys = Object.keys(Object(next))
|
|||
|
for (var j = 0, n = keys.length; j < n; j++) {
|
|||
|
var key = keys[j]
|
|||
|
var desc = Object.getOwnPropertyDescriptor(next, key)
|
|||
|
if (desc !== undefined && desc.enumerable) to[key] = next[key]
|
|||
|
}
|
|||
|
}
|
|||
|
return to
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
if (!Array.from) {
|
|||
|
Object.defineProperty(Array, 'from', {
|
|||
|
enumerable: false,
|
|||
|
value: (function() {
|
|||
|
var toStr = Object.prototype.toString
|
|||
|
var isCallable = function(fn) {
|
|||
|
return (
|
|||
|
typeof fn === 'function' || toStr.call(fn) === '[object Function]'
|
|||
|
)
|
|||
|
}
|
|||
|
|
|||
|
var toInt = function(val) {
|
|||
|
var num = val - 0
|
|||
|
if (isNaN(num)) return 0
|
|||
|
|
|||
|
if (num === 0 || isFinite(num)) return num
|
|||
|
|
|||
|
return (num > 0 ? 1 : -1) * Math.floor(Math.abs(num))
|
|||
|
}
|
|||
|
var maxInt = Math.pow(2, 53) - 1
|
|||
|
var toLen = function(val) {
|
|||
|
var len = toInt(val)
|
|||
|
return Math.min(Math.max(len, 0), maxInt)
|
|||
|
}
|
|||
|
|
|||
|
return function(arrLike) {
|
|||
|
var _this = this
|
|||
|
var items = Object(arrLike)
|
|||
|
if (arrLike === null)
|
|||
|
throw new TypeError(
|
|||
|
'Array.from requires an array-like object - not null or undefined'
|
|||
|
)
|
|||
|
|
|||
|
var mapFn = arguments.length > 1 ? arguments[1] : undefined
|
|||
|
var other
|
|||
|
if (mapFn !== undefined) {
|
|||
|
if (!isCallable(mapFn))
|
|||
|
throw new TypeError(
|
|||
|
'Array.from: when provided, the second argument must be a function'
|
|||
|
)
|
|||
|
|
|||
|
if (arguments.length > 2) other = arguments[2]
|
|||
|
}
|
|||
|
|
|||
|
var len = toLen(items.length)
|
|||
|
var arr = isCallable(_this) ? Object(new _this(len)) : new Array(len)
|
|||
|
var k = 0
|
|||
|
var kVal
|
|||
|
while (k < len) {
|
|||
|
kVal = items[k]
|
|||
|
if (mapFn)
|
|||
|
arr[k] =
|
|||
|
other === 'undefined'
|
|||
|
? mapFn(kVal, k)
|
|||
|
: mapFn.call(other, kVal, k)
|
|||
|
else arr[k] = kVal
|
|||
|
|
|||
|
k++
|
|||
|
}
|
|||
|
arr.length = len
|
|||
|
return arr
|
|||
|
}
|
|||
|
})()
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// 判断数组是否包含指定元素
|
|||
|
if (!Array.prototype.includes) {
|
|||
|
Object.defineProperty(Array.prototype, 'includes', {
|
|||
|
value: function(val) {
|
|||
|
for (var i in this) {
|
|||
|
if (this[i] === val) return true
|
|||
|
}
|
|||
|
return false
|
|||
|
},
|
|||
|
enumerable: false
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
//类似于Array 的splice方法
|
|||
|
if (!String.prototype.splice) {
|
|||
|
Object.defineProperty(String.prototype, 'splice', {
|
|||
|
value: function(start, len, fill) {
|
|||
|
var length = this.length,
|
|||
|
argLen = arguments.length
|
|||
|
|
|||
|
fill = fill === undefined ? '' : fill
|
|||
|
|
|||
|
if (argLen < 1) {
|
|||
|
return this
|
|||
|
}
|
|||
|
|
|||
|
//处理负数
|
|||
|
if (start < 0) {
|
|||
|
if (Math.abs(start) >= length) start = 0
|
|||
|
else start = length + start
|
|||
|
}
|
|||
|
|
|||
|
if (argLen === 1) {
|
|||
|
return this.slice(0, start)
|
|||
|
} else {
|
|||
|
len -= 0
|
|||
|
|
|||
|
var strl = this.slice(0, start),
|
|||
|
strr = this.slice(start + len)
|
|||
|
|
|||
|
return strl + fill + strr
|
|||
|
}
|
|||
|
},
|
|||
|
enumerable: false
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
if (!Date.prototype.getFullWeek) {
|
|||
|
//获取当天是本年度第几周
|
|||
|
Object.defineProperty(Date.prototype, 'getFullWeek', {
|
|||
|
value: function() {
|
|||
|
var thisYear = this.getFullYear(),
|
|||
|
that = new Date(thisYear, 0, 1),
|
|||
|
firstDay = that.getDay() || 1,
|
|||
|
numsOfToday = (this - that) / 86400000
|
|||
|
return Math.ceil((numsOfToday + firstDay) / 7)
|
|||
|
},
|
|||
|
enumerable: false
|
|||
|
})
|
|||
|
|
|||
|
//获取当天是本月第几周
|
|||
|
Object.defineProperty(Date.prototype, 'getWeek', {
|
|||
|
value: function() {
|
|||
|
var today = this.getDate(),
|
|||
|
thisMonth = this.getMonth(),
|
|||
|
thisYear = this.getFullYear(),
|
|||
|
firstDay = new Date(thisYear, thisMonth, 1).getDay()
|
|||
|
return Math.ceil((today + firstDay) / 7)
|
|||
|
},
|
|||
|
enumerable: false
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
if (!Date.isDate) {
|
|||
|
Object.defineProperty(Date, 'isDate', {
|
|||
|
value: function(obj) {
|
|||
|
return typeof obj === 'object' && obj.getTime ? true : false
|
|||
|
},
|
|||
|
enumerable: false
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
//时间格式化
|
|||
|
if (!Date.prototype.format) {
|
|||
|
Object.defineProperty(Date.prototype, 'format', {
|
|||
|
value: function(str) {
|
|||
|
str = str || 'Y-m-d H:i:s'
|
|||
|
var week = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
|||
|
dt = {
|
|||
|
fullyear: this.getFullYear(),
|
|||
|
year: this.getYear(),
|
|||
|
fullweek: this.getFullWeek(),
|
|||
|
week: this.getWeek(),
|
|||
|
month: this.getMonth() + 1,
|
|||
|
date: this.getDate(),
|
|||
|
day: week[this.getDay()],
|
|||
|
hours: this.getHours(),
|
|||
|
minutes: this.getMinutes(),
|
|||
|
seconds: this.getSeconds()
|
|||
|
},
|
|||
|
re
|
|||
|
|
|||
|
dt.g = dt.hours > 12 ? dt.hours - 12 : dt.hours
|
|||
|
|
|||
|
re = {
|
|||
|
Y: dt.fullyear,
|
|||
|
y: dt.year,
|
|||
|
m: dt.month < 10 ? '0' + dt.month : dt.month,
|
|||
|
n: dt.month,
|
|||
|
d: dt.date < 10 ? '0' + dt.date : dt.date,
|
|||
|
j: dt.date,
|
|||
|
H: dt.hours < 10 ? '0' + dt.hours : dt.hours,
|
|||
|
h: dt.g < 10 ? '0' + dt.g : dt.g,
|
|||
|
G: dt.hours,
|
|||
|
g: dt.g,
|
|||
|
i: dt.minutes < 10 ? '0' + dt.minutes : dt.minutes,
|
|||
|
s: dt.seconds < 10 ? '0' + dt.seconds : dt.seconds,
|
|||
|
W: dt.fullweek,
|
|||
|
w: dt.week,
|
|||
|
D: dt.day
|
|||
|
}
|
|||
|
|
|||
|
for (var i in re) {
|
|||
|
str = str.replace(new RegExp(i, 'g'), re[i])
|
|||
|
}
|
|||
|
return str
|
|||
|
},
|
|||
|
enumerable: false
|
|||
|
})
|
|||
|
}
|
|||
|
/*-----------------部分ES6的JS实现 ending---------------*/
|