1. Use JavaScript in HTML
async: Load external script file, inform browser to download immediately and execute asynchronously
defer: scripts can be delayed until the document is fully parsed and displayed
noscript:
The browser does not support scripts.
Browsers support scripts, but scripts are disabled
2. Variables, scopes and memory problems
Duplicate variable values
- Duplicate the basic type values. The two variables are independent of each other and do not affect each other.
- Duplicate the reference type (object) and the value reference is a pointer. Changing one object affects another.
function setName(obj) { obj.name = "Nicholas"; obj = new Object(); obj.name = "Greg"; } var person = new Object(); setName(person); alert(person.name); //"Nicholas"
When a function overrides obj, the variable reference is a local object. This object is destroyed immediately after the function is executed.
Detection type
Using typeof to detect the basic data type is not very useful in detecting the value of the reference type, because using typeof cannot know what type of object it is. For this purpose, ECMAScript provides the instanceof operator.
var s = 'test'; var b = true; var i = 22; var u; var n = null; var o = new Object() console.log(typeof s); // string console.log(typeof b); // boolean console.log(typeof i); // number console.log(typeof u); // undefined console.log(typeof n); // object console.log(typeof o); // object
Extended Scope Chain
Catch block in try-catch statement
with statement
Garbage collection
Mark Clearance
- When the garbage collector runs, it marks all variables stored in memory.
Reference Counting
- When they are assigned a value to point to an object, subtract 1 from the reference count of the object they originally hold, and then add 1 to the reference count of the object they newly point to. When their lifetime is over, subtract 1 from the reference count of the object they are pointing to, and when the reference count is zero, the memory space they occupy can be recovered.
3. Reference type
Array type
Detection array
value instanceof Array Array.isArray(value)
Stack method (LIFO)
- push: Add parameters one by one to the end of the data
- pop: Remove the last item from the end of the array
Queue method (FIFO)
- shift: Delete the first item of the array and return it
- unshift: Add any item to the front of the array and return the length of the new array
Reordering method
- reverse: inverted array
- sort: Array in ascending order
Operating method
- concat: Add parameters to the end of the array and return a new array
- Slice: Create a new array based on one or more items in the current array. The slice() method can accept one or two parameters, that is, until the beginning and end of the item to be returned
var colors = ['red', 'green', 'blue', 'yellow', 'purple']; var colors2 = colors.slice(1) var colors3 = colors.slice(4) console.log(colors2); // ["green", "blue", "yellow", "purple"] console.log(colors3); // ["purple"]
- splice: Returns a new array capable of deleting, inserting, and replacing multiple items
var colors = ["red", "green", "blue"]; var removed = colors.splice(0,1); // Delete the first item alert(colors); // green,blue alert(removed); // red, which returns an array containing only one item removed = colors.splice(1, 0, "yellow", "orange"); // Insert two items from position 1 alert(colors); // green,yellow,orange,blue alert(removed); // Returns an empty array removed = colors.splice(1, 1, "red", "purple"); // Insert two items and delete one alert(colors); // green,red,purple,orange,blue alert(removed); // yellow, only one item is included in the returned array
Position method
- indexOf: Looking backwards from the beginning of the array
- lastIndexOf: Look forward from the end of the array
Iterative method
- every(): Runs a given function for each item in the array, and returns true if the function returns true for each item.
- filter(): Run a given function for each item in the array, and returning the function returns an array of true items.
- forEach(): Runs the given function for each item in the array. This method does not return a value.
- map(): Run a given function for each item in the array, returning an array of the results of each function call.
- some(): Run a given function for each item in the array, and return true if the function returns true for any item.
Reduction method
- reduce(): traverses all items of the array and returns the final value, starting with the first item, one by one, to the end
- ReducRight (): Start with the last item and go through it one by one to the first.
var values = [1, 2, 3, 4, 5]; var sum = values.reduce((prev, cur, index, array) => { return prev + cur; }); console.log(sum); // 15
Function type
Internal attributes of functions
- There are two special objects inside the function: argumens and this
Attributes and methods
Each function contains two attributes
- length: Represents the number of named parameters the function wants to receive
- prototype: Save instance method
Each function contains two non-inherited methods
- Both call() and apply() methods are used to call functions in a specific scope, which is actually equivalent to setting the value of this object in the function body.
- apply() receives two parameters: one is the scope of the function in which it runs, and the other is an array of parameters.
- call() received parameters, the first parameter is that this value has not changed, the change is that the remaining parameters are passed directly to the function.
- The bind() method creates an instance whose this value is bound to the value passed to the bind() function.
function sum (num1, num2) { return num1 + num2; } function callSum1 (num1, num2) { return sum.apply(this, [num1, num2]); } function callSum2 (num1, num2) { return sum.call(this, num1, num2); } callSum1(10, 10); // 20 callSum2(10, 10); // 20 var callSum3 = sum.bind(null) callSum3(10, 10) // 20
Single-body built-in object
Global object
- The encodeURI() and encodeURIComponet() methods can encode URIs for sending to browsers.
The result of encoding encodeURI() is that all characters except spaces remain unchanged. Only spaces are replaced by% 20, corresponding to decodeURI() method.
- The encodeURIComponet() method replaces all non-alphanumeric characters with the corresponding encoding, which is why encodeURI() can be used for the entire URL, but only for strings appended to the existing URL. Corresponding decodeURIComponet() method
4. Object-Oriented Programming
Understanding objects
Attribute type
There are two attributes in ECMAScript: data attributes and accessor attributes
Data attributes
- [[Configurable]: Indicates whether attributes can be redefined by deleting attributes, whether attributes can be modified, or whether attributes can be changed to accessor attributes, with a default value of true
- [[Enumerable]: Indicates whether properties can be returned through a for-in loop. The default value is true
- [[Writable]: Indicates whether the value of an attribute can be modified. The default value is true
- [[Value]: Data value containing this attribute, default undefined
To modify the default properties of attributes, you must use the Object.defineProperty() method. This method takes three parameters: the object in which the attribute is located, the name of the attribute and a descriptor object. Among them, the attributes of the descriptor object must be: configurabel, enumerable, writable, and value. Set one or more of these values.
var person = {} Object.defineProperty(person, 'name', { writable: false, configurable: false, value: 'Nicholas' }); console.log(person.name); // Nicholas person.name = 'Greg'; console.log(person.name); // Nicholas delete person.name console.log(person.name); // Nicholas
The Object.defineProperty() method restricts the modification of configurable to false attributes
Accessor properties
- [[Configurable]: Indicates whether attributes can be redefined by deleting attributes, whether attributes can be modified, or whether attributes can be modified to data attributes. The default value is true
- [[Enumerable]: Indicates whether properties can be returned through a for-in loop. The default value is true
- [[Get]: A function called when reading a property. The default value is undefined
- [[Set]: A function that is called when a property is written. The default value is undefined
Accessor attributes cannot be defined directly. Object.defineProperty() must be used to define them.
var book = { _year: 2004, edition: 1 }; Object.defineProperty(book, 'year', { get: function() { return this._year }, set: function(newValue) { if (newValue > 2004) { this._year = newValue; this.edition += newValue - 2004 } } }); book.year = 2005; console.log(book.edition); // 2
Define multiple attributes
ECMAScript5 defines an Object.defineProperties() method. Using this method, multiple attributes can be defined at one time by descriptors. This method receives two object parameters.
var book = {}; Object.defineProperties(book, { _year: { value: 2004 }, edition: { value: 1 }, year: { get: function() { return this._year }, set: function(newValue) { if (newValue > 2004) { this._year = newValue; this.edition += newValue - 2004 } } } });
Characteristics of read attributes
Using the Object.getOwnPropertyDescriptor() method, you can get the descriptor of a given attribute
var descriptor = Object.getOwnPropertyDescriptor(book, '_year') console.log(descriptor.value); // 2004 console.log(descriptor.configurable); // false
create object
Factory model
function createPerson (name, age, job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function () { console.log(this.name); }; return o; } var person1 = createPerson('Nicholas', 29, 'Software Engineer'); var person2 = createPerson('Greg', 27, 'Doctor');
Constructor Pattern
function Person (name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function () { console.log(this.name); }; } var person1 = new Person('Nicholas', 29, 'Software Engineer'); var person2 = new Person('Greg', 27, 'Doctor');
Prototype pattern
Understanding prototype objects
function Person () {} Person.prototype.name = 'Nicholas'; Person.prototype.age = 29; Person.prototype.job = 'Software Engineer'; Person.prototype.sayName = function () { console.log(this.name); }; var person1 = new Person(); var person2 = new Person();
By default, all prototype objects automatically get a constructor property that contains a pointer to the function where a prototype property resides. For example, Person.prototype.constructor points to Person
We can use the isPrototypeof() method to determine whether there is a prototype relationship between objects. Essentially, if [[Prototype]] points to the object calling the isPrototypeof() method (Person.prototye), then the method returns true.
console.log(Person.prototype.isPrototypeOf(person1)); // true console.log(Person.prototype.isPrototypeOf(person2)); // true
ECMAScript5 adds a new method called Object.getPrototypeOf(), which returns the value of [[Prototype]] in all supported implementations. For example:
console.log(Object.getPrototypeOf(person1) === Person.prototype); // true
Although the values stored in the prototype can be accessed through the object instance, the values in the prototype can not be rewritten by the object instance. If we add an attribute to an instance with the same name as an attribute in the instance prototype, we create the attribute in the instance, which will mask the attribute in the prototype.
function Person() {} Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function() { alert(this.name); }; var person1 = new Person(); person1.name = "Greg"; console.log(person1.name); //"Greg" - from an example delete person1.name; console.log(person1.name); //"Nicholas" - from the prototype
By deleting the attribute of the instance through the delete operator, the connection to the name attribute in the prototype is restored. So the next call to person1.name is to return the value of the name attribute in the prototype.
The Object.hasOwnProperty() method can detect whether an attribute exists in an instance or in a prototype.
Prototype and in operator
- The in operator returns true as long as attributes are accessible to objects, and Object.hasOwnProperty() returns true only if attributes exist in instances, so as long as the in operator returns true and Object.hasOwnProperty() returns false, it can be determined that attributes are attributes in the prototype.
function hasPrototypeProperty (object, name) { if (name in object) { return object.hasOwnProperty(name) // true: attribute in the instance, false: attribute in the object } else { console.log('No such attribute'); } }
- To obtain all enumerable instance attributes on an object, you can use the Object.keys() method of ECMAScript5
function Person () {} Person.prototype.name = 'Nicholas'; Person.prototype.age = 29; Person.prototype.job = 'Software Engineer'; Person.prototype.sayName = function () { console.log(this.name); }; Object.keys(Person.prototype); // ["name", "age", "job", "sayName"] var person1 = new Person(); person1.name = 'Rob'; person1.age = 31; Object.keys(person1); // ["name", "age"]
- Object.getOwnPropertyNames() can get all attributes, whether or not it is enumerable
Object.getOwnPropertyNames(Person.prototype); // ["constructor", "name", "age", "job", "sayName"]
A simpler prototyping approach
function Person () {} Person.prototype = { name: 'Nicholas', age: 29, job: 'Software Engineer', sayName: function () { console.log(this.name); } }
We set Person.prototype as a new object, essentially rewriting the default prototype object completely. However, there is an exception, where the constructor attribute no longer points to Person, but to Object. So we need to set his constructor property to Person
function Person () {} Person.prototype = { constructor: Person, name: 'Nicholas', age: 29, job: 'Software Engineer', sayName: function () { console.log(this.name); } }
But resetting the constructor attribute in this way will cause its [[Enumerable]] feature to be set to true, and by default, the native constructor attribute is not enumerated.
function Person () {} Person.prototype = { name: 'Nicholas', age: 29, job: 'Software Engineer', sayName: function () { console.log(this.name); } } Object.defineProperty(Person.prototype, 'constructor', { enumerable: false, value: Person });
Dynamics of Prototypes
Rewriting the entire prototype object severs the connection between the constructor and the original prototype. Remember: the pointer in the instance points only to the prototype, not to the constructor
function Person () {} var friend = new Person(); Person.prototype = { constructor: Person, name: 'Nicholas', age: 29, job: 'Software Engineer', sayName: function () { console.log(this.name); } } friend.sayName(); // error
Prototype of Native Object
The importance of prototype patterns is not only in creating custom types, but also in creating all native reference types. All native reference types (Object, Array, String, etc.) define methods on the prototype of their constructors.
The Problem of Prototype Objects
By default, all instances of the prototype schema will get the same attribute values. The biggest problem is the shared nature of the prototype schema.
function Person () {} Person.prototype = { constructor: Person, name: 'Nicholas', age: 29, job: 'Software Engineer', friends: ['Shelby', 'Court'], sayName: function () { console.log(this.name); } } var person1 = new Person(); var person2 = new Person(); person1.friends.push('Van'); console.log(person1.friends); // ["Shelby", "Court", "Van"] console.log(person2.friends); // ["Shelby", "Court", "Van"]
Combining constructors and prototypes
The most common way to create custom types is to use constructor patterns to define instance attributes and prototype patterns to define methods and shared attributes.
Each instance will have its own copy of instance attributes, but colleagues share references to methods, which saves the most memory.
function Person (name, age, job) { this.name = name; this.age = age; this.job = job; this.friends = ['Shelby', 'Court']; } Person.prototype = { constructor: Person, sayName: function () { console.log(this.name); }; } var person1 = new Person('Nicholas', 29, 'Software Engineer'); var person2 = new Person('Greg', 27, 'Doctor'); person1.friends.push('Van'); console.log(person1.friends); // ["Shelby", "Court", "Van"] console.log(person2.friends); // ["Shelby", "Court"]
Dynamic prototype model
By initializing the prototype in the constructor (only if necessary), the advantages of using both the constructor and the prototype schema are maintained. In other words, you can determine whether prototypes need to be initialized by checking whether a method that should exist is valid.
function Person (name, age, job) { this.name = name; this.age = age; this.job = job; this.friends = ['Shelby', 'Court']; if (typeof this.sayName === 'function') { Person.prototype.sayName = function () { console.log(this.name); }; } }
inherit
Prototype chain
Relationships among constructors, prototypes and instances: Each constructor has a prototype object, which contains a pointer to the constructor, and an instance contains an internal pointer to the prototype object.
function SuperType () { this.property = true; } SuperType.prototype.getSuperValue = function () { return this.property }; function SubType () { this.subproperty = false } // Inherited SuperType SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function () { return this.subproperty; }; var instance = new SubType(); console.log(instance.getSuperValue()); // true
Don't forget the default prototype
By default, all reference types used inherit Object, which is also implemented through prototype chains. The default prototype of all functions is an instance of Object, so the default prototype contains an internal pointer to Object.prototype.
Determine the relationship between prototypes and examples
instanceof operator
console.log(instance instanceof Object); // true console.log(instance instanceof SuperType); // true console.log(instance instanceof SubType); // true
The isPrototypeOf() method, as long as it is a prototype that has appeared in the prototype chain, can be said to be the prototype of an instance derived from the prototype chain.
console.log(Object.isPrototypeOf(instance)); // true console.log(SuperType.isPrototypeOf(instance)); // true console.log(SubType.isPrototypeOf(instance)); // true
A prudent definition
Subtypes sometimes need to override a method in a supertype, or add a method that does not exist in a supertype. Nevertheless, the code that adds methods to the prototype must be placed after replacing the prototype statement.
The Problem of Prototype Chain
- When inheritance is achieved through prototypes, prototypes actually become instances of another type, and prototype attributes containing reference type values are shared by all instances.
- When creating an instance of a subtype, you cannot pass parameters to a supertype constructor.
Borrowing constructors
In the process of solving the problems caused by the inclusion of reference type values in prototypes, borrowed constructor techniques are used. Calling a supertype constructor inside a subtype constructor
function SuperType () { this.colors = ['red', 'blue', 'green']; } function SubType () { // Inherited SuperType SuperType.call(this); // SuperType.apply(this); } var instance1 = new SubType(); instance1.colors.push('black'); console.log(instance1.colors); // ["red", "blue", "green", "black"] var instance2 = new SubType(); console.log(instance2.colors); // ["red", "blue", "green"]
Transfer parameters
Compared with prototype chains, borrowing constructors has a great advantage in transferring parameters to supertype constructors in subtype constructors.
function SuperType (name) { this.name = name; } function SubType () { // Inherited SuperType SuperType.call(this, 'Nicholas'); this.age = 29 } var instance = new SubType(); console.log(instance.name); // 'Nicholas' console.log(instance.age); // 29
The Problem of Borrowing Constructor
Methods are defined in constructors, because function reuse is out of the question.
Combinatorial Inheritance
Function reuse can be realized by defining methods on prototypes, and each instance can have its own properties.
function SuperType (name) { this.name = name; this.colors = ['red', 'blue', 'green']; } SuperType.prototype.sayName = function () { console.log(this.name); }; function SubType (name, age) { // Inherited SuperType SuperType.call(this, name); this.age = age } // Inherited SuperType SubType.prototype = new SuperType(); SubType.prototype.sayAge = function () { console.log(this.age); }; var instance1 = new SubType('Nicholas', 29); instance1.colors.push('black'); console.log(instance1.colors); // ["red", "blue", "green", "black"] instance1.sayName(); // 'Nicholas' instance1.sayAge(); // 29 var instance2 = new SubType('Greg', 27); console.log(instance2.colors); // ["red", "blue", "green"] instance2.sayName(); // 'Greg' instance2.sayAge(); // 27
5. Functional expression
There are two ways to define functions: one is function declaration, the other is function expression.
Function declarations are characterized by elevation of function declarations, meaning that the function declarations are read before the code is executed.
closure
Functional scoping chain
When a function is called for the first time, an execution environment and corresponding scope chain are created, and the scope chain is assigned to a special internal property (that is, [[Scope]). Then, the active object of the function is initialized with the values of this.arguments and other named parameters. But in the scope chain, the active object of the external function is always in the second place, and the active object of the external function is always in the third place,... Until the global execution environment as the end point of the scope chain.
Closures and variables
// i ended up at 10 function createFunctions () { var result = new Array(); for (var i = 0; i < 10; i++) { result[i] = function () { return i } } return result; } // i is 0, 1, 2, 9 function createFunctions () { var result = new Array(); for (var i = 0; i < 10; i++) { result[i] = function (num) { return function (arguments) { return num; }; }(i) } return result; }
On this object
This object is bound to the execution environment of a function in operation: in a global function, this is equal to window, and when a function is called as a method of an object, this is equal to that object. However, the execution environment of anonymous functions is global, so its this object usually points to window. Of course, if you change the execution environment of the execution function by call() and apply(), this will point to other objects.
var name = 'The Window'; var object = { name: 'My Object', getNameFunc: function () { return function () { return this.name } } } console.log(object.getNameFunc()()); // 'The Window'
Imitate Block Scope
Anonymous functions can be used to mimic block-level scopes and avoid this problem. The syntax for using anonymous functions with block-level scopes (commonly referred to as private scopes) is shown below.
(function(){ })()
private variable
function Person(name) { this.getName = function() { retirm name; } this.setName = function(value) { name = value } } var person = new Person('Nicholas'); console.log(person.getName()); // 'Nicholas' person.setName('Greg'); console.log(person.getName()); // 'Greg'
Two privilege methods are defined in the constructor of the above code: getName() and setName(). Both methods can be used outside the constructor and have access to the private variable name. But outside the Person constructor, there is no way to access name. Since these two methods are defined within the constructor, they can be accessed as closures through the scope chain.
Static private variables
6.BOM
Windows object
global scope
Regardless of the fact that global variables are attributes of windows objects, there is a difference between defining global variables and defining them directly on windows objects: global variables cannot be deleted by delete attribute operators, but attributes defined directly on Windows objects can be deleted.
var age = 29; window.color = 'red'; delete window.age; // No error reporting delete window.color // Return true without error var newValue = oldValue; // Errors are thrown because oldValue is undefined var newValue = window.oldValue; // No error is reported, because this is an attribute query
Window Relations and Framework
Understanding frameset and frame
window position
The following code allows you to cross-browser locations to the left and top of the window
Opera supports screenX, screenY. Other browsers support screenLeft, screenTop
var leftPops = (typeof window.screenLeft === 'number') ? window.screenLeft : window.screenX; var topPops = (typeof window.screenTop === 'number') ? window.screenLeft : window.screenY;
Localization object
Attributes of locatoin objects
- replace method replaces the current browser window, reload method refreshes the browser window
navigator object
Identify Browser Information
7.DOM
DOM is an API for HTML and XML documents. DOM depicts a hierarchical node tree.
Node hierarchy
NODE type
Each node has a nodeType attribute that indicates the type of node.
- Node.ELEMENT_NODE(1)
- Node.ATTRIBUTE_NODE(2)
- Node.TEXT_NODE(3)
- Node.CDATA_SECTION_NODE(4)
- Node.ENTITY_REFERENCE_NODE(5)
- Node.ENTITY_NODE(6)
- Node.PROCESSING_INSTRUCTION_NODE(7)
- Node.COMMENT_NODE(8)
- Node.DOCUMENT_NODE(9)
- Node.DOCUMENT_TYPE_NODE(10)
- Node.DOCUMENT_FRAGMENT_NODE(11)
- Node.NOTATION_NODE(12)
if (someNode.nodeType == 1) { console.log('Node is an element'); }
nodeName and nodeValue attributes
NoeName returns the label name of the node, such as p, div, span, etc.
The value of nodeValue is always null
Node Relations
Operating Node
- appendChild(): Add a node to the end of the childNodes list
- insertBefore(): Add a node to a specific location in the child Nodes list. This method takes two parameters: the node to be inserted and the node to be inserted as a reference, and returns the node to be inserted. If the reference node is null, appendChild() performs the same operation.
- replaceChild(): Replace nodes. Receive two parameters, the node to be inserted and the node to be replaced. The node to be replaced will be returned and removed from the document book.
- removeChild(): Remove nodes. Receiving a parameter is the node that needs to be removed
- cloneNode(): Create an identical copy of the method node that calls it. Accept a Boolean parameter to indicate whether deep replication is performed
- normalize()
- createElement(): Create elements
- createTextNode(): Create text nodes
- createComment(): Create annotation nodes
8.DOM Extension
Selector API
- getElementById() method: obtained by id
- getElementsByName() method: Through the name attribute, it is generally used to obtain form elements, with less use.
- getElementsByTagName() method: Get elements by tag name
- getElementsByClassName() method: Get elements by class name
- querySelector() method: Receives a CSS selector, returns the first element that matches the pattern, and returns null if it does not.
- querySelectorAll() method: Receives a CSS selector and returns an instance of NodeList
- macthsSelector() method: Receives a CSS selector and returns true if the calling element matches that selector or false otherwise
9. Events
Event streams
Event Bubbling
Event streams in IE are called event bubbles, in which events begin to be received by the most specific elements and then propagate up to less specific nodes step by step.
Event capture
Netscape's event flow is called event capture, that is, less specific nodes should receive events earlier, and the most specific nodes should receive events last.
DOM Event Flow
There are three stages: event capture stage. In the target stage and event bubbling stage
Event Handler
DOM2-level Time Processor
addEventListener
removeEventListener
Two methods are defined to handle the operation of specifying and deleting event handlers. All DOM nodes contain these two methods, accepting three parameters: event name, event handler and Boolean value. Finally, if the Boolean value is true, it means that the event handler is invoked in the capture phase; false means that the event handler is invoked in the bubble phase, and the default is false.
Event handlers added through addEventListener() can only be removed using removeEventListener(). Anonymous functions added through addEventListener() cannot be removed. Input functions must be the same, otherwise they cannot be removed
attachEvent
detachEvent
The two methods take two parameters: the event name (with on) and the event handler.
var btn = document.getElementById('myBtn');
var handler = function(){ console.log('clicked') };
btn.attachEvent('onclick', handler);
btn.detachEvent('onclick', handler); //Effective
Event object
DOM Event Object
Event type
UI events
load: When the page is fully loaded and triggered on the window, the img image is loaded.
unload: When the page is completely uninstalled
abort: When the user stops downloading
Error: Triggered in Windows when a JavaScript error occurs
select: When the user selects one or more triggers in the text box
resize: triggers when the window size changes
scroll: Triggered when the user scrolls
Memory and performance
Event delegation takes advantage of time bubbles and specifies an event handler to manage all events of a certain type.
HTML5 scripting
Cross-document messaging
The core method is the postMessage() method, which takes two parameters: a message and a string representing which domain the message receiver comes from.
// Note: All XDM-enabled browsers also support iframe's content window properties
var iframeWindow = document.getElementById('myframe').contentWindow; iframeWindow.postMessage('A secret', 'http://www.wrox.com');
Advanced Skills
Advanced Functions
Secure Type Detection
function isArray (value) { return Object.prototype.toString.call(value) === '[object Array]'; } function isFunction (value) { return Object.prototype.toString.call(value) === '[object Function]'; } function isRegExp (value) { return Object.prototype.toString.call(value) === '[object RegExp]'; }
Scope-safe constructors
Prevent this from pointing to window s objects
function Person (name, age, job) { if (this instanceof Person) { this.name = name; this.age = age; this.job = job; } else { return new Person(name, age, jon); } } //Inert Load Function function createXHR(){ if (typeof XMLHttpRequest != "undefined"){ return new XMLHttpRequest(); } else if (typeof ActiveXObject != "undefined"){ if (typeof arguments.callee.activeXString != "string"){ var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"], i,len; for (i=0,len=versions.length; i < len; i++){ try { new ActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; break; } catch (ex){ //skip } } } return new ActiveXObject(arguments.callee.activeXString); } else { throw new Error("No XHR object available."); } }
The first method is: function createXHR () { if (typeof XMLHttpRequest != 'undefined') { createXHR = function () { return new XMLHttpRequest(); }; } else if (typeof ActiveXObjext != 'undefined') { createXHR = function () { if (typeof arguments.callee.activeXString != 'string') { var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"], i,len; for (i = 0, len = versions.length; i < len; i++) { try { new ActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; break; } catch (e) { // skip } } } return new ActiveXObject(arguments.callee.activeXString); }; } else { createXHR = function () { throw new Error('No XHR object available.'); } } return createXHR(); } //The second amendment: var createXHR = (function () { if (typeof XMLHttpRequest != 'undefined') { return function () { return new XMLHttpRequest(); }; } else if (typeof ActiveXObjext != 'undefined') { return function () { if (typeof arguments.callee.activeXString != 'string') { var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"], i,len; for (i = 0, len = versions.length; i < len; i++) { try { new ActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; break; } catch (e) { // skip } } } return new ActiveXObject(arguments.callee.activeXString); }; } else { return function () { throw new Error('No XHR object available.'); } } })();
Function binding
bind Function: function bind (fn, context) { return function () { fn.call(context, arguments) } }
currying function curry (fn) { var args = Array.prototype.slice.call(arguments, 1); return function () { var innerArgs = Array.prototype.slice.call(arguments) var finalArgs = args.concat(innerArgs) return fn.apply(null, finalArgs); } } function bind (fn, context) { var args = Array.prototype.slice.call(arguments, 2); return function () { var innerArgs = Array.prototype.slice.call(arguments) var finalArgs = args.concat(innerArgs) return fn.apply(context, finalArgs); } }