学无所长,一事无成
分类: JavaScript
2015-05-29 17:49:02
since: | v0.9 |
---|
dojo/_base/lang 包含多个函数用于支持多种泛型以及语言结构,dojo toolkit 的其他部分都是基于此。
同其他基于 dojo/_base 的模块类似,如果你使用传统方式运行 Dojo loader (即使用参数 async:false),则本模块可以自动加载。在模块自动加载完毕后,你还可以随时通过 require 来引用此模块,访问其函数:
克隆 objects 或 nodes,返回一个新的实体出来(具体看输入的是什么)。注意返回的是实体,不是引用。即你给 clone()传入任何实体,它就创造并返回该实体的一个新版本。
有时你会想克隆一个 DOM 节点。最简单的方法就是用 定位 DOM 节点,确保在克隆后修改其 id(因为 ID 在文档中是唯一的,而且文档就是使用 ID 来组织的)。
TODOC clone and event objects.
根据传入的 object 生成一个新的对象,这个新的对象没有的属性都会到传入的 object 中去查找,你可以传入一组属性来设置返回的新对象。
这是 JavaScript 中 Boodman/Crockford 委派模式的一个实现子集。一个中间对象构造器会调解返回对象的原型链,当对象本身某个属性找不到的时候,会向下委派到 delegate() 中传入的那个对象进行查找。这个非常类似于 ES4 中的 swrap() ,除了它是基于纯粹的对象而非 types 来运作的。
此方法的函数签名如下:
Name | 类型 | 描述 |
---|---|---|
obj | Object | The object to delegate to for properties not found directly on the return object or in props. |
props | Object... | An object containing properties to assign to the returned object. |
Check if all objects in a dot-separated string object path exist, such as "A.B.C".
exists() is a convenience function, particularly useful for testing long object paths. It accepts a string as its first parameter, and walks down the path it represents. You can optionally provide a root for the path as a second parameter, otherwise it will use a default value of the global object. Each portion of the .delimited string is tested for defined-ness, returning true only if each object exists as defined in the strong.
The second root parameter is optional, exists() will use the value of by default (which is usually the current window). You can use it to root the path in a different window object, or a particular namespace:
extend() works much like , though works directly on an object’s prototype. extend() mixes members from the right-most object into the first object, modifying the object directly.
This can be used to extend functionality into existing classes. Consider the following:
The way the works, a custom attribute on the node will be recognized, as in the interest of performance, only declared members are mixed as part of the parsing process. Before the above extend()call, this sample would not recognize the follow markup:
After the extend, any new instances of a dijit/TitlePane will have the randomAttribute member mixed into the instance. extend() affects all future instances of a class or prototyped Object.
A potentially confusing result of the above actually provides us a lot of flexibility. All Dijit widgets inherit from in one way or another. Some widgets, like the can contain arbitrary widgets, though require a region parameter on the contained widget, though rather than manually adding a region parameter to each declaration across Dijit, the BorderContainer simply extendsdijit/_WidgetBase with the member, and anyone using any widget within a BorderContainer can specify aregion:
The side-effect of this is a documentation nightmare. Now every widget appears to have a region variable, when in fact it is just there for the benefit of BorderContainer. As a side note, this has been addressed in the API Viewer and other documentation as “extension” properties, methods and events and can be easily identified and filtered out.
getObject() returns the property of an object from a dot-separated string such as A.B.C.
The simplest way to use getObject() is to pass a dot-separated string as shown below:
getObject() also takes an optional boolean parameter which, if true, will create the property if it does not exist. Any other properties along the path will also be created along the way. The default value is false.
You can also pass an object as the third parameter. This will define the context in which to search for the property. By default, the context is .
hitch() returns a function that will execute a given function in a given context. This function allows you to control how a function executes, particularly in asynchronous operations. Sometimes code will be written like this:
Only to have it fail with a cryptic error about an unresolved variable? Why does that occur? Well, because in asynchronous callbacks such as above, the context that the code is executing in has changed. It will no longer refer to the object that originally provided it, but its context will now refer to the enclosing object, the callback. To get around this, you can use hitch() to force the function to retain its original context. The same code done properly will look like:
And now when the event fires and runs the function, this will refer to the context that is expected.
Looking in the console, bar should be printed. That is because the scope provided in hitch() was myObj, so inside the function, this refers to myObj.
To call a method in a given context that is already in scope, just the method name as a string can be passed as the second argument:
The console output should be bar.
Arguments can also be passed to the function that is being called:
The output in the console should be baz bar. Any arguments provided after the first two will be passed to the function.
mixin() is a simple utility function for mixing objects together. Mixin combines two objects from right to left, overwriting the left-most object, and returning the newly mixed object for use. mixin() is very similar to but only works on objects, whereas extend explicitly extends an object’s prototype.
Note: In case of nested objects and arrays, mixin does not combine, only overwrite.
Merge two objects (join two objects) together with mixin():
This example overwrites the d member from the second object, leaving the variable a with three members: b, d, and g. To expand on this, we can illustrate how to use mixin to overwrite defaults for some function:
This will create and play a fadeIn animation passing and onEnd function and node, using a default duration.
Mixin modifies the first object in the list, mixing in second object. If you wish to make an entirely new object from the mixed results, you have a couple options. First, clone the existing object with , and then mix:
Here, the return from clone() is a new object, then b is mixed in.
Alternately, you can pass an empty object as the first mix, and mix another object into it. You can then repeat this pattern as often as you’d like:
Just remember the object instance in the first position will always be overwritten, and the right-most object will take precedence in the mix.
A common pattern when creating class objects is to pass an object-hash of properties to the constructor.mixin() provides a technique for easy override of default in you own classes. Consider the follow class declaration:
Now, any time we create a new instance of a Thinger, it will have a member variable defaultValue set to red. If we provide a new defaultValue, the constructor will immediately overwrite the existing one:
Sometimes is it useful to mix custom variables and members into instances of widgets and other objects. Mixing into an instance allows you to easily add arbitrary references or overwrite functionality after instantiation.
Now, that instance of the ContentPane as a Date object attached in the _timeCreated member, which is accessible to the widget as this._timeCreated.
If you want to mix in some methods into an instance using two previous techniques, be aware that decorates them, while mixin() does not, which may affect how this.inherited()works, if used in mixed-in methods. Use , which correctly handles all properties in dojo/_base/declare-compatible way.
partial() is related to in that it is a function that returns a function. What it does is allow manipulation of the arguments being passed to a function. It allows the first n arguments to be fixed to a specific value, but the remaining arguments to vary.
Let’s take a quick look at a pseudo-code example of using partial:
Okay, so that will invoke the dataLoaded function when the request.get() function is fullfulled... but the success callback expects to pass on data, ioArgs. So how the heck do we make sure that the expectations are honored even with that new first param called someFirstParam? Use partial(). Here’s how you would do it:
What that does is create a new function that wraps dataLoaded and affixes the first parameter with the value firstValue. Note that partial() allows you to do n parameters, so you can keep defining as many values as you want for fixed-value parameters of a function.
This function provides a light-weight foundation for substitution-based templating. It is a sane alternative to string concatenation technique, which is brittle and doesn’t play nice with localization.
If the second argument is an object, all names within braces are interpreted as property names within this object. All names separated by . (dot) will be interpreted as sub-objects. This default behavior provides greater flexibility:
You don’t need to use all properties of an object, you can list them in any order, and you can reuse them as many times as you like.
In most cases you may prefer an array notation effectively simulating the venerable printf:
For ultimate flexibility you can use replace() with a function as the second argument.
Essentially these arguments are the same as in String.replace() when a function is used. Usually the second argument is the most useful one.
Let’s take a look at example where we are calculating values lazily on demand from a potentially dynamic source.
This code in action:
In some cases you may want to use different braces, for example because your interpolated strings contain patterns similar to {abc}, but they should not be evaluated and replaced, or your server-side framework already uses these patterns for something else. In this case you should replace the pattern:
It is advised for the new pattern to be:
This example escapes substituted text for HTML to prevent possible exploits. Dijit templates implement similar technique. We will also borrow Dijit syntax: where all names starting with ! are going to be placed as is (e.g., {!abc}), while everything else is going to be escaped.
Let’s add a simple formatting to substituted fields. We will use the following notation in this example:
In this example we are going to format numbers as fixed or exponential with optional precision.
Set a property from a dot-separated string, such as A.B.C. In JavaScript, a dot separated string likeobj.parent.child refers to an item called child inside an object called parent inside of obj. setObject() will let you set the value of child, creating the intermediate parent objects if they don’t exist.
Without setObject(), it is often handle like this:
Whereas with setObject(), we can shorten that to:
This function implements a frequently required functionality: it removes white-spaces from both ends of a string. This functionality is part of ECMAScript 5 standard and implemented by some browsers. In this case trim() delegates to the native implementation. More information can be found here: String.trim() at MDC.
trim() implementation was informed by Steven Levithan’s blog post. It was chosen to implement the compact yet performant version. If your application requires even more speed, check out, which implements the fastest version.
The following methods are deprecated. See for advice on how to differentiate between different types of objects without using methods(). The methods below are deprecated:
isString()
Checks if the parameter is a String
isArray()
Checks if the parameter is an Array
isFunction()
Checks if the parameter is a Function
isObject()
Checks if the parameter is a Object
isArrayLike()
Checks if the parameter is like an Array
isAlien()
Checks if the parameter is a built-in function