Skip to content

Commit c67685b

Browse files
committed
use more efficient Object check
1 parent 1f3175b commit c67685b

File tree

8 files changed

+86
-57
lines changed

8 files changed

+86
-57
lines changed

src/compiler.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,15 @@ function Compiler (vm, options) {
107107
compiler.setupObserver()
108108

109109
// initialize data
110-
var data = compiler.data = options.data || {}
110+
var data = compiler.data = options.data || {},
111+
defaultData = options.defaultData
112+
if (defaultData) {
113+
for (key in defaultData) {
114+
if (!hasOwn.call(data, key)) {
115+
data[key] = defaultData[key]
116+
}
117+
}
118+
}
111119

112120
// copy paramAttributes
113121
var params = options.paramAttributes

src/directive.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,7 @@ function parseFilter (filter, compiler) {
135135
* during initialization.
136136
*/
137137
DirProto.update = function (value, init) {
138-
var type = utils.typeOf(value)
139-
if (init || value !== this.value || type === 'Object' || type === 'Array') {
138+
if (init || value !== this.value || (value && typeof value === 'object')) {
140139
this.value = value
141140
if (this._update) {
142141
this._update(

src/directives/repeat.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,12 @@ module.exports = {
3333

3434
update: function (collection) {
3535

36-
if (utils.typeOf(collection) === 'Object') {
37-
collection = utils.objectToArray(collection)
36+
if (!Array.isArray(collection)) {
37+
if (utils.isObject(collection)) {
38+
collection = utils.objectToArray(collection)
39+
} else {
40+
utils.warn('v-repeat only accepts Array or Object values.')
41+
}
3842
}
3943

4044
// if initiating with an empty collection, we need to
@@ -50,7 +54,7 @@ module.exports = {
5054
this.oldCollection = this.collection
5155
collection = this.collection = collection || []
5256

53-
var isObject = collection[0] && utils.typeOf(collection[0]) === 'Object'
57+
var isObject = collection[0] && utils.isObject(collection[0])
5458
this.vms = this.oldCollection
5559
? this.diff(collection, isObject)
5660
: this.init(collection, isObject)

src/filters.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ filters.orderBy.computed = true
168168
*/
169169
function contains (val, search) {
170170
/* jshint eqeqeq: false */
171-
if (utils.typeOf(val) === 'Object') {
171+
if (utils.isObject(val)) {
172172
for (var key in val) {
173173
if (contains(val[key], search)) {
174174
return true

src/main.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ function extend (options) {
9898

9999
var ParentVM = this
100100

101+
// extend data options need to be copied
102+
// on instantiation
103+
if (options.data) {
104+
options.defaultData = options.data
105+
delete options.data
106+
}
107+
101108
// inherit options
102109
options = inheritOptions(options, ParentVM.options, true)
103110
utils.processOptions(options)
@@ -149,10 +156,8 @@ function inheritOptions (child, parent, topLevel) {
149156
for (var key in parent) {
150157
if (key === 'el') continue
151158
var val = child[key],
152-
parentVal = parent[key],
153-
type = utils.typeOf(val),
154-
parentType = utils.typeOf(parentVal)
155-
if (topLevel && type === 'Function' && parentVal) {
159+
parentVal = parent[key]
160+
if (topLevel && typeof val === 'function' && parentVal) {
156161
// merge hook functions into an array
157162
child[key] = [val]
158163
if (Array.isArray(parentVal)) {
@@ -162,7 +167,7 @@ function inheritOptions (child, parent, topLevel) {
162167
}
163168
} else if (
164169
topLevel &&
165-
(type === 'Object' || parentType === 'Object')
170+
(utils.isTrueObject(val) || utils.isTrueObject(parentVal))
166171
&& !(parentVal instanceof ViewModel)
167172
) {
168173
// merge toplevel object options

src/observer.js

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,17 @@
33
var Emitter = require('./emitter'),
44
utils = require('./utils'),
55
// cache methods
6-
typeOf = utils.typeOf,
76
def = utils.defProtected,
7+
isObject = utils.isObject,
8+
isArray = Array.isArray,
89
hasOwn = ({}).hasOwnProperty,
910
oDef = Object.defineProperty,
1011
slice = [].slice,
11-
// types
12-
OBJECT = 'Object',
13-
ARRAY = 'Array',
1412
// fix for IE + __proto__ problem
1513
// define methods as inenumerable if __proto__ is present,
1614
// otherwise enumerable so we can loop through and manually
1715
// attach to array instances
18-
hasProto = ({}).__proto__,
19-
// lazy load
20-
ViewModel
16+
hasProto = ({}).__proto__
2117

2218
// Array Mutation Handlers & Augmentations ------------------------------------
2319

@@ -157,9 +153,7 @@ def(ObjProxy, '$delete', function (key) {
157153
* Check if a value is watchable
158154
*/
159155
function isWatchable (obj) {
160-
ViewModel = ViewModel || require('./viewmodel')
161-
var type = typeOf(obj)
162-
return (type === OBJECT || type === ARRAY) && !(obj instanceof ViewModel)
156+
return typeof obj === 'object' && obj && !obj.$compiler
163157
}
164158

165159
/**
@@ -196,11 +190,10 @@ function propagateChange (obj) {
196190
* Watch target based on its type
197191
*/
198192
function watch (obj) {
199-
var type = typeOf(obj)
200-
if (type === OBJECT) {
201-
watchObject(obj)
202-
} else if (type === ARRAY) {
193+
if (isArray(obj)) {
203194
watchArray(obj)
195+
} else {
196+
watchObject(obj)
204197
}
205198
}
206199

@@ -279,7 +272,7 @@ function convertKey (obj, key) {
279272
function init (val, propagate) {
280273
values[key] = val
281274
emitter.emit('set', key, val, propagate)
282-
if (Array.isArray(val)) {
275+
if (isArray(val)) {
283276
emitter.emit('set', key + '.length', val.length, propagate)
284277
}
285278
observe(val, key, emitter)
@@ -293,11 +286,11 @@ function convertKey (obj, key) {
293286
* all of its properties.
294287
*/
295288
function emitSet (obj) {
296-
var type = typeOf(obj),
297-
emitter = obj && obj.__emitter__
298-
if (type === ARRAY) {
289+
var emitter = obj && obj.__emitter__
290+
if (!emitter) return
291+
if (isArray(obj)) {
299292
emitter.emit('set', 'length', obj.length)
300-
} else if (type === OBJECT) {
293+
} else {
301294
var key, val
302295
for (key in obj) {
303296
val = obj[key]
@@ -314,19 +307,18 @@ function emitSet (obj) {
314307
* emit a set event with undefined value.
315308
*/
316309
function copyPaths (newObj, oldObj) {
317-
if (typeOf(oldObj) !== OBJECT || typeOf(newObj) !== OBJECT) {
310+
if (!isObject(newObj) || !isObject(oldObj)) {
318311
return
319312
}
320-
var path, type, oldVal, newVal
313+
var path, oldVal, newVal
321314
for (path in oldObj) {
322315
if (!(hasOwn.call(newObj, path))) {
323316
oldVal = oldObj[path]
324-
type = typeOf(oldVal)
325-
if (type === OBJECT) {
317+
if (isArray(oldVal)) {
318+
newObj[path] = []
319+
} else if (isObject(oldVal)) {
326320
newVal = newObj[path] = {}
327321
copyPaths(newVal, oldVal)
328-
} else if (type === ARRAY) {
329-
newObj[path] = []
330322
} else {
331323
newObj[path] = undefined
332324
}
@@ -348,7 +340,7 @@ function ensurePath (obj, key) {
348340
}
349341
obj = obj[sec]
350342
}
351-
if (typeOf(obj) === OBJECT) {
343+
if (isObject(obj)) {
352344
sec = path[i]
353345
if (!(hasOwn.call(obj, sec))) {
354346
obj[sec] = undefined

src/utils.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ var config = require('./config'),
55
timeout = win.setTimeout,
66
def = Object.defineProperty,
77
THIS_RE = /[^\w]this[^\w]/,
8+
OBJECT = 'object',
89
hasClassList = 'classList' in document.documentElement,
910
ViewModel // late def
1011

@@ -90,11 +91,18 @@ var utils = module.exports = {
9091
},
9192

9293
/**
93-
* Accurate type check
94-
* internal use only, so no need to check for NaN
94+
* A less bullet-proof but more efficient type check
95+
* than Object.prototype.toString
9596
*/
96-
typeOf: function (obj) {
97-
return toString.call(obj).slice(8, -1)
97+
isObject: function (obj) {
98+
return typeof obj === OBJECT && obj && !Array.isArray(obj)
99+
},
100+
101+
/**
102+
* A more accurate but less efficient type check
103+
*/
104+
isTrueObject: function (obj) {
105+
return toString.call(obj) === '[object Object]'
98106
},
99107

100108
/**
@@ -192,7 +200,7 @@ var utils = module.exports = {
192200
*/
193201
toConstructor: function (obj) {
194202
ViewModel = ViewModel || require('./viewmodel')
195-
return utils.typeOf(obj) === 'Object'
203+
return utils.isObject(obj)
196204
? ViewModel.extend(obj)
197205
: typeof obj === 'function'
198206
? obj
@@ -284,7 +292,7 @@ var utils = module.exports = {
284292
var res = [], val, data
285293
for (var key in obj) {
286294
val = obj[key]
287-
data = utils.typeOf(val) === 'Object'
295+
data = utils.isObject(val)
288296
? val
289297
: { $value: val }
290298
data.$key = key

test/unit/specs/utils.js

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -112,18 +112,31 @@ describe('Utils', function () {
112112

113113
})
114114

115-
describe('typeOf', function () {
115+
describe('isObject', function () {
116116

117-
it('should return correct type', function () {
118-
var tof = utils.typeOf
119-
assert.equal(tof({}), 'Object')
120-
assert.equal(tof([]), 'Array')
121-
assert.equal(tof(1), 'Number')
122-
assert.equal(tof(''), 'String')
123-
assert.equal(tof(true), 'Boolean')
124-
// phantomjs weirdness
125-
assert.ok(tof(null) === 'Null' || tof(null) === 'DOMWindow')
126-
assert.ok(tof(undefined) === 'Undefined' || tof(undefined) === 'DOMWindow')
117+
it('should return correct result', function () {
118+
var iso = utils.isObject
119+
assert.ok(iso({}))
120+
assert.notOk(iso([]))
121+
assert.notOk(iso(1))
122+
assert.notOk(iso(true))
123+
assert.notOk(iso(null))
124+
assert.notOk(iso(undefined))
125+
})
126+
127+
})
128+
129+
describe('isTrueObject', function () {
130+
131+
it('should return correct result', function () {
132+
var iso = utils.isTrueObject
133+
assert.ok(iso({}))
134+
assert.notOk(iso([]))
135+
assert.notOk(iso(1))
136+
assert.notOk(iso(true))
137+
assert.notOk(iso(null))
138+
assert.notOk(iso(undefined))
139+
assert.notOk(iso(document.createElement('div')))
127140
})
128141

129142
})
@@ -264,9 +277,9 @@ describe('Utils', function () {
264277
it('should convert plain object components & elements to constructors', function () {
265278
var components = options.components
266279
assert.ok(components.a.prototype instanceof Vue)
267-
assert.strictEqual(components.a.options.data.data, 1)
280+
assert.strictEqual(components.a.options.defaultData.data, 1)
268281
assert.ok(components.b.prototype instanceof Vue)
269-
assert.strictEqual(components.b.options.data.data, 2)
282+
assert.strictEqual(components.b.options.defaultData.data, 2)
270283
})
271284

272285
})

0 commit comments

Comments
 (0)