1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2006 The Closure Library Authors. All Rights Reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Licensed under the Apache License, Version 2.0 (the "License");
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// you may not use this file except in compliance with the License.
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// You may obtain a copy of the License at
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//      http://www.apache.org/licenses/LICENSE-2.0
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Unless required by applicable law or agreed to in writing, software
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// distributed under the License is distributed on an "AS-IS" BASIS,
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// See the License for the specific language governing permissions and
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// limitations under the License.
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @fileoverview Utilities for manipulating objects/maps/hashes.
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.provide('goog.object');
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Calls a function for each element in an object/map/hash.
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object over which to iterate.
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {function(this:T,V,?,Object.<K,V>):?} f The function to call
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     for every element. This function takes 3 arguments (the element, the
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     index and the object) and the return value is ignored.
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {T=} opt_obj This is used as the 'this' object within f.
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template T,K,V
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.forEach = function(obj, f, opt_obj) {
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    f.call(opt_obj, obj[key], key, obj);
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Calls a function for each element in an object/map/hash. If that call returns
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * true, adds the element to a new object.
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object over which to iterate.
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {function(this:T,V,?,Object.<K,V>):boolean} f The function to call
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     for every element. This
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     function takes 3 arguments (the element, the index and the object)
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     and should return a boolean. If the return value is true the
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     element is added to the result object. If it is false the
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     element is not included.
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {T=} opt_obj This is used as the 'this' object within f.
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {!Object.<K,V>} a new object in which only elements that passed the
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     test are present.
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template T,K,V
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.filter = function(obj, f, opt_obj) {
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var res = {};
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (f.call(opt_obj, obj[key], key, obj)) {
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      res[key] = obj[key];
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return res;
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * For every element in an object/map/hash calls a function and inserts the
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * result into a new object.
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object over which to iterate.
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {function(this:T,V,?,Object.<K,V>):R} f The function to call
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     for every element. This function
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     takes 3 arguments (the element, the index and the object)
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     and should return something. The result will be inserted
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     into a new object.
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {T=} opt_obj This is used as the 'this' object within f.
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {!Object.<K,R>} a new object with the results from f.
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template T,K,V,R
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.map = function(obj, f, opt_obj) {
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var res = {};
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    res[key] = f.call(opt_obj, obj[key], key, obj);
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return res;
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Calls a function for each element in an object/map/hash. If any
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * call returns true, returns true (without checking the rest). If
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * all calls return false, returns false.
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object to check.
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {function(this:T,V,?,Object.<K,V>):boolean} f The function to
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     call for every element. This function
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     takes 3 arguments (the element, the index and the object) and should
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     return a boolean.
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {T=} opt_obj This is used as the 'this' object within f.
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {boolean} true if any element passes the test.
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template T,K,V
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.some = function(obj, f, opt_obj) {
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (f.call(opt_obj, obj[key], key, obj)) {
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return true;
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return false;
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Calls a function for each element in an object/map/hash. If
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * all calls return true, returns true. If any call returns false, returns
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * false at this point and does not continue to check the remaining elements.
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object to check.
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {?function(this:T,V,?,Object.<K,V>):boolean} f The function to
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     call for every element. This function
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     takes 3 arguments (the element, the index and the object) and should
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     return a boolean.
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {T=} opt_obj This is used as the 'this' object within f.
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {boolean} false if any element fails the test.
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template T,K,V
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.every = function(obj, f, opt_obj) {
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!f.call(opt_obj, obj[key], key, obj)) {
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return false;
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the number of key-value pairs in the object map.
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} obj The object for which to get the number of key-value
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     pairs.
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {number} The number of key-value pairs in the object map.
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.getCount = function(obj) {
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // JS1.5 has __count__ but it has been deprecated so it raises a warning...
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // in other words do not use. Also __count__ only includes the fields on the
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // actual object and not in the prototype chain.
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var rv = 0;
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    rv++;
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return rv;
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns one key from the object map, if any exists.
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * For map literals the returned key will be the first one in most of the
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * browsers (a know exception is Konqueror).
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} obj The object to pick a key from.
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {string|undefined} The key or undefined if the object is empty.
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.getAnyKey = function(obj) {
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return key;
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns one value from the object map, if any exists.
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * For map literals the returned value will be the first one in most of the
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * browsers (a know exception is Konqueror).
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object to pick a value from.
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {V|undefined} The value or undefined if the object is empty.
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template K,V
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.getAnyValue = function(obj) {
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return obj[key];
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Whether the object/hash/map contains the given object as a value.
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * An alias for goog.object.containsValue(obj, val).
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object in which to look for val.
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {V} val The object for which to check.
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {boolean} true if val is present.
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template K,V
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.contains = function(obj, val) {
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return goog.object.containsValue(obj, val);
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the values of the object/map/hash.
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object from which to get the values.
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {!Array.<V>} The values in the object/map/hash.
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template K,V
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.getValues = function(obj) {
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var res = [];
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var i = 0;
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    res[i++] = obj[key];
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return res;
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the keys of the object/map/hash.
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} obj The object from which to get the keys.
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {!Array.<string>} Array of property keys.
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.getKeys = function(obj) {
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var res = [];
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var i = 0;
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    res[i++] = key;
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return res;
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Get a value from an object multiple levels deep.  This is useful for
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * pulling values from deeply nested objects, such as JSON responses.
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Example usage: getValueByKeys(jsonObj, 'foo', 'entries', 3)
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!Object} obj An object to get the value from.  Can be array-like.
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {...(string|number|!Array.<number|string>)} var_args A number of keys
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     (as strings, or numbers, for array-like objects).  Can also be
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     specified as a single array of keys.
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {*} The resulting value.  If, at any point, the value for a key
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     is undefined, returns undefined.
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.getValueByKeys = function(obj, var_args) {
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var isArrayLike = goog.isArrayLike(var_args);
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var keys = isArrayLike ? var_args : arguments;
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Start with the 2nd parameter for the variable parameters syntax.
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var i = isArrayLike ? 0 : 1; i < keys.length; i++) {
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    obj = obj[keys[i]];
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!goog.isDef(obj)) {
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return obj;
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Whether the object/map/hash contains the given key.
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} obj The object in which to look for key.
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {*} key The key for which to check.
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {boolean} true If the map contains the key.
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.containsKey = function(obj, key) {
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return key in obj;
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Whether the object/map/hash contains the given value. This is O(n).
276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object in which to look for val.
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {V} val The value for which to check.
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {boolean} true If the map contains the value.
280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template K,V
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.containsValue = function(obj, val) {
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (obj[key] == val) {
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return true;
286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return false;
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Searches an object for an element that satisfies the given condition and
294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * returns its key.
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object to search in.
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {function(this:T,V,string,Object.<K,V>):boolean} f The
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *      function to call for every element. Takes 3 arguments (the value,
298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     the key and the object) and should return a boolean.
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {T=} opt_this An optional "this" context for the function.
300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {string|undefined} The key of an element for which the function
301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     returns true or undefined if no such element is found.
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template T,K,V
303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.findKey = function(obj, f, opt_this) {
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (f.call(opt_this, obj[key], key, obj)) {
307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return key;
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return undefined;
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Searches an object for an element that satisfies the given condition and
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * returns its value.
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object to search in.
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {function(this:T,V,string,Object.<K,V>):boolean} f The function
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     to call for every element. Takes 3 arguments (the value, the key
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     and the object) and should return a boolean.
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {T=} opt_this An optional "this" context for the function.
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {V} The value of an element for which the function returns true or
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     undefined if no such element is found.
324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template T,K,V
325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.findValue = function(obj, f, opt_this) {
327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var key = goog.object.findKey(obj, f, opt_this);
328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return key && obj[key];
329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Whether the object/map/hash is empty.
334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} obj The object to test.
336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {boolean} true if obj is empty.
337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.isEmpty = function(obj) {
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Removes all key value pairs from the object/map/hash.
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} obj The object to clear.
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.clear = function(obj) {
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var i in obj) {
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    delete obj[i];
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Removes a key-value pair based on the key.
360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} obj The object from which to remove the key.
362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {*} key The key to remove.
363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {boolean} Whether an element was removed.
364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.remove = function(obj, key) {
366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var rv;
367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if ((rv = key in obj)) {
368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    delete obj[key];
369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return rv;
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Adds a key-value pair to the object. Throws an exception if the key is
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * already in use. Use set if you want to change an existing pair.
377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object to which to add the key-value pair.
379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {string} key The key to add.
380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {V} val The value to add.
381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template K,V
382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.add = function(obj, key, val) {
384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (key in obj) {
385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    throw Error('The object already contains the key "' + key + '"');
386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  goog.object.set(obj, key, val);
388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the value for the given key.
393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object from which to get the value.
395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {string} key The key for which to get the value.
396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {R=} opt_val The value to return if no item is found for the given
397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     key (default is undefined).
398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {V|R|undefined} The value for the given key.
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template K,V,R
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.get = function(obj, key, opt_val) {
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (key in obj) {
403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return obj[key];
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return opt_val;
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Adds a key-value pair to the object/map/hash.
411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object to which to add the key-value pair.
413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {string} key The key to add.
414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {V} value The value to add.
415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template K,V
416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.set = function(obj, key, value) {
418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  obj[key] = value;
419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
422cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
423cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Adds a key-value pair to the object/map/hash if it doesn't exist yet.
424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj The object to which to add the key-value pair.
426cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {string} key The key to add.
427cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {V} value The value to add if the key wasn't present.
428cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {V} The value of the entry at the end of the function.
429cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template K,V
430cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.setIfUndefined = function(obj, key, value) {
432cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return key in obj ? obj[key] : (obj[key] = value);
433cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
437cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Does a flat clone of the object.
438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<K,V>} obj Object to clone.
440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {!Object.<K,V>} Clone of the input object.
441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template K,V
442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.clone = function(obj) {
444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We cannot use the prototype trick because a lot of methods depend on where
445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // the actual key is set.
446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var res = {};
448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    res[key] = obj[key];
450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return res;
452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We could also use goog.mixin but I wanted this to be independent from that.
453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Clones a value. The input may be an Object, Array, or basic type. Objects and
458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * arrays will be cloned recursively.
459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * WARNINGS:
461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * <code>goog.object.unsafeClone</code> does not detect reference loops. Objects
462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * that refer to themselves will cause infinite recursion.
463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * <code>goog.object.unsafeClone</code> is unaware of unique identifiers, and
465cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * copies UIDs created by <code>getUid</code> into cloned results.
466cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {*} obj The value to clone.
468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {*} A clone of the input value.
469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.unsafeClone = function(obj) {
471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var type = goog.typeOf(obj);
472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (type == 'object' || type == 'array') {
473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (obj.clone) {
474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return obj.clone();
475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var clone = type == 'array' ? [] : {};
477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (var key in obj) {
478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      clone[key] = goog.object.unsafeClone(obj[key]);
479cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return clone;
481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return obj;
484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns a new object in which all the keys and values are interchanged
489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * (keys become values and values become keys). If multiple keys map to the
490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * same value, the chosen transposed value is implementation-dependent.
491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} obj The object to transpose.
493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {!Object} The transposed object.
494cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.transpose = function(obj) {
496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var transposed = {};
497cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var key in obj) {
498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    transposed[obj[key]] = key;
499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return transposed;
501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * The names of the fields that are defined on Object.prototype.
506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @type {Array.<string>}
507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @private
508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.PROTOTYPE_FIELDS_ = [
510cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  'constructor',
511cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  'hasOwnProperty',
512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  'isPrototypeOf',
513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  'propertyIsEnumerable',
514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  'toLocaleString',
515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  'toString',
516cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  'valueOf'
517cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)];
518cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
519cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
520cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
521cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Extends an object with another object.
522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * This operates 'in-place'; it does not create a new Object.
523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
524cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Example:
525cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * var o = {};
526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * goog.object.extend(o, {a: 0, b: 1});
527cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * o; // {a: 0, b: 1}
528cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * goog.object.extend(o, {b: 2, c: 3});
529cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * o; // {a: 0, b: 2, c: 3}
530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
531cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} target The object to modify. Existing properties will be
532cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     overwritten if they are also present in one of the objects in
533cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     {@code var_args}.
534cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {...Object} var_args The objects from which values will be copied.
535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.extend = function(target, var_args) {
537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var key, source;
538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var i = 1; i < arguments.length; i++) {
539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    source = arguments[i];
540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (key in source) {
541cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      target[key] = source[key];
542cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
543cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
544cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // For IE the for-in-loop does not contain any properties that are not
545cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // enumerable on the prototype object (for example isPrototypeOf from
546cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Object.prototype) and it will also not include 'replace' on objects that
547cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // extend String and change 'replace' (not that it is common for anyone to
548cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // extend anything except Object).
549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
550cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (var j = 0; j < goog.object.PROTOTYPE_FIELDS_.length; j++) {
551cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      key = goog.object.PROTOTYPE_FIELDS_[j];
552cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (Object.prototype.hasOwnProperty.call(source, key)) {
553cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        target[key] = source[key];
554cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
555cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
556cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
557cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
558cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
559cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
560cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
561cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Creates a new object built from the key-value pairs provided as arguments.
562cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {...*} var_args If only one argument is provided and it is an array
563cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     then this is used as the arguments,  otherwise even arguments are used as
564cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     the property names and odd arguments are used as the property values.
565cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {!Object} The new object.
566cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @throws {Error} If there are uneven number of arguments or there is only one
567cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     non array argument.
568cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
569cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.create = function(var_args) {
570cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var argLength = arguments.length;
571cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (argLength == 1 && goog.isArray(arguments[0])) {
572cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return goog.object.create.apply(null, arguments[0]);
573cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
574cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
575cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (argLength % 2) {
576cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    throw Error('Uneven number of arguments');
577cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
578cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
579cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var rv = {};
580cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var i = 0; i < argLength; i += 2) {
581cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    rv[arguments[i]] = arguments[i + 1];
582cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
583cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return rv;
584cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
585cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
586cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
587cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
588cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Creates a new object where the property names come from the arguments but
589cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * the value is always set to true
590cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {...*} var_args If only one argument is provided and it is an array
591cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     then this is used as the arguments,  otherwise the arguments are used
592cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     as the property names.
593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {!Object} The new object.
594cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
595cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.createSet = function(var_args) {
596cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var argLength = arguments.length;
597cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (argLength == 1 && goog.isArray(arguments[0])) {
598cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return goog.object.createSet.apply(null, arguments[0]);
599cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
600cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
601cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var rv = {};
602cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var i = 0; i < argLength; i++) {
603cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    rv[arguments[i]] = true;
604cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
605cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return rv;
606cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
607cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
608cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
609cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
610cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Creates an immutable view of the underlying object, if the browser
611cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * supports immutable objects.
612cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
613cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * In default mode, writes to this view will fail silently. In strict mode,
614cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * they will throw an error.
615cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *
616cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!Object.<K,V>} obj An object.
617cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {!Object.<K,V>} An immutable view of that object, or the
618cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *     original object if this browser does not support immutables.
619cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @template K,V
620cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
621cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.createImmutableView = function(obj) {
622cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var result = obj;
623cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (Object.isFrozen && !Object.isFrozen(obj)) {
624cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    result = Object.create(obj);
625cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Object.freeze(result);
626cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
627cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return result;
628cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
629cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
630cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
631cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
632cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!Object} obj An object.
633cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {boolean} Whether this is an immutable view of the object.
634cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
635cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.object.isImmutableView = function(obj) {
636cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return !!Object.isFrozen && Object.isFrozen(obj);
637cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
638