lang.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. var Dep = require('../observer/dep')
  2. /**
  3. * Check is a string starts with $ or _
  4. *
  5. * @param {String} str
  6. * @return {Boolean}
  7. */
  8. exports.isReserved = function (str) {
  9. var c = (str + '').charCodeAt(0)
  10. return c === 0x24 || c === 0x5F
  11. }
  12. /**
  13. * Guard text output, make sure undefined outputs
  14. * empty string
  15. *
  16. * @param {*} value
  17. * @return {String}
  18. */
  19. exports.toString = function (value) {
  20. return value == null
  21. ? ''
  22. : value.toString()
  23. }
  24. /**
  25. * Check and convert possible numeric strings to numbers
  26. * before setting back to data
  27. *
  28. * @param {*} value
  29. * @return {*|Number}
  30. */
  31. exports.toNumber = function (value) {
  32. if (typeof value !== 'string') {
  33. return value
  34. } else {
  35. var parsed = Number(value)
  36. return isNaN(parsed)
  37. ? value
  38. : parsed
  39. }
  40. }
  41. /**
  42. * Convert string boolean literals into real booleans.
  43. *
  44. * @param {*} value
  45. * @return {*|Boolean}
  46. */
  47. exports.toBoolean = function (value) {
  48. return value === 'true'
  49. ? true
  50. : value === 'false'
  51. ? false
  52. : value
  53. }
  54. /**
  55. * Strip quotes from a string
  56. *
  57. * @param {String} str
  58. * @return {String | false}
  59. */
  60. exports.stripQuotes = function (str) {
  61. var a = str.charCodeAt(0)
  62. var b = str.charCodeAt(str.length - 1)
  63. return a === b && (a === 0x22 || a === 0x27)
  64. ? str.slice(1, -1)
  65. : false
  66. }
  67. /**
  68. * Camelize a hyphen-delmited string.
  69. *
  70. * @param {String} str
  71. * @return {String}
  72. */
  73. exports.camelize = function (str) {
  74. return str.replace(/-(\w)/g, toUpper)
  75. }
  76. function toUpper (_, c) {
  77. return c ? c.toUpperCase() : ''
  78. }
  79. /**
  80. * Hyphenate a camelCase string.
  81. *
  82. * @param {String} str
  83. * @return {String}
  84. */
  85. exports.hyphenate = function (str) {
  86. return str
  87. .replace(/([a-z\d])([A-Z])/g, '$1-$2')
  88. .toLowerCase()
  89. }
  90. /**
  91. * Converts hyphen/underscore/slash delimitered names into
  92. * camelized classNames.
  93. *
  94. * e.g. my-component => MyComponent
  95. * some_else => SomeElse
  96. * some/comp => SomeComp
  97. *
  98. * @param {String} str
  99. * @return {String}
  100. */
  101. var classifyRE = /(?:^|[-_\/])(\w)/g
  102. exports.classify = function (str) {
  103. return str.replace(classifyRE, toUpper)
  104. }
  105. /**
  106. * Simple bind, faster than native
  107. *
  108. * @param {Function} fn
  109. * @param {Object} ctx
  110. * @return {Function}
  111. */
  112. exports.bind = function (fn, ctx) {
  113. return function (a) {
  114. var l = arguments.length
  115. return l
  116. ? l > 1
  117. ? fn.apply(ctx, arguments)
  118. : fn.call(ctx, a)
  119. : fn.call(ctx)
  120. }
  121. }
  122. /**
  123. * Convert an Array-like object to a real Array.
  124. *
  125. * @param {Array-like} list
  126. * @param {Number} [start] - start index
  127. * @return {Array}
  128. */
  129. exports.toArray = function (list, start) {
  130. start = start || 0
  131. var i = list.length - start
  132. var ret = new Array(i)
  133. while (i--) {
  134. ret[i] = list[i + start]
  135. }
  136. return ret
  137. }
  138. /**
  139. * Mix properties into target object.
  140. *
  141. * @param {Object} to
  142. * @param {Object} from
  143. */
  144. exports.extend = function (to, from) {
  145. for (var key in from) {
  146. to[key] = from[key]
  147. }
  148. return to
  149. }
  150. /**
  151. * Quick object check - this is primarily used to tell
  152. * Objects from primitive values when we know the value
  153. * is a JSON-compliant type.
  154. *
  155. * @param {*} obj
  156. * @return {Boolean}
  157. */
  158. exports.isObject = function (obj) {
  159. return obj !== null && typeof obj === 'object'
  160. }
  161. /**
  162. * Strict object type check. Only returns true
  163. * for plain JavaScript objects.
  164. *
  165. * @param {*} obj
  166. * @return {Boolean}
  167. */
  168. var toString = Object.prototype.toString
  169. var OBJECT_STRING = '[object Object]'
  170. exports.isPlainObject = function (obj) {
  171. return toString.call(obj) === OBJECT_STRING
  172. }
  173. /**
  174. * Array type check.
  175. *
  176. * @param {*} obj
  177. * @return {Boolean}
  178. */
  179. exports.isArray = Array.isArray
  180. /**
  181. * Define a non-enumerable property
  182. *
  183. * @param {Object} obj
  184. * @param {String} key
  185. * @param {*} val
  186. * @param {Boolean} [enumerable]
  187. */
  188. exports.define = function (obj, key, val, enumerable) {
  189. Object.defineProperty(obj, key, {
  190. value: val,
  191. enumerable: !!enumerable,
  192. writable: true,
  193. configurable: true
  194. })
  195. }
  196. /**
  197. * Define a reactive property.
  198. *
  199. * @param {Object} obj
  200. * @param {String} key
  201. * @param {*} val
  202. */
  203. exports.defineReactive = function (obj, key, val) {
  204. var dep = new Dep()
  205. Object.defineProperty(obj, key, {
  206. get: function metaGetter () {
  207. if (Dep.target) {
  208. dep.depend()
  209. }
  210. return val
  211. },
  212. set: function metaSetter (newVal) {
  213. if (val !== newVal) {
  214. val = newVal
  215. dep.notify()
  216. }
  217. }
  218. })
  219. }
  220. /**
  221. * Debounce a function so it only gets called after the
  222. * input stops arriving after the given wait period.
  223. *
  224. * @param {Function} func
  225. * @param {Number} wait
  226. * @return {Function} - the debounced function
  227. */
  228. exports.debounce = function (func, wait) {
  229. var timeout, args, context, timestamp, result
  230. var later = function () {
  231. var last = Date.now() - timestamp
  232. if (last < wait && last >= 0) {
  233. timeout = setTimeout(later, wait - last)
  234. } else {
  235. timeout = null
  236. result = func.apply(context, args)
  237. if (!timeout) context = args = null
  238. }
  239. }
  240. return function () {
  241. context = this
  242. args = arguments
  243. timestamp = Date.now()
  244. if (!timeout) {
  245. timeout = setTimeout(later, wait)
  246. }
  247. return result
  248. }
  249. }
  250. /**
  251. * Manual indexOf because it's slightly faster than
  252. * native.
  253. *
  254. * @param {Array} arr
  255. * @param {*} obj
  256. */
  257. exports.indexOf = function (arr, obj) {
  258. var i = arr.length
  259. while (i--) {
  260. if (arr[i] === obj) return i
  261. }
  262. return -1
  263. }
  264. /**
  265. * Make a cancellable version of an async callback.
  266. *
  267. * @param {Function} fn
  268. * @return {Function}
  269. */
  270. exports.cancellable = function (fn) {
  271. var cb = function () {
  272. if (!cb.cancelled) {
  273. return fn.apply(this, arguments)
  274. }
  275. }
  276. cb.cancel = function () {
  277. cb.cancelled = true
  278. }
  279. return cb
  280. }
  281. /**
  282. * Check if two values are loosely equal - that is,
  283. * if they are plain objects, do they have the same shape?
  284. *
  285. * @param {*} a
  286. * @param {*} b
  287. * @return {Boolean}
  288. */
  289. exports.looseEqual = function (a, b) {
  290. /* eslint-disable eqeqeq */
  291. return a == b || (
  292. exports.isObject(a) && exports.isObject(b)
  293. ? JSON.stringify(a) === JSON.stringify(b)
  294. : false
  295. )
  296. /* eslint-enable eqeqeq */
  297. }