Zepto source code analysis, zepto source code
Today, I took the time to review the source code of Zepto and annotate it according to my own understanding. You are welcome to make a brick. Source code version: v1.1.4 Source: http://zeptojs.com/
After analyzing the overall code, sort out the architecture diagram:
This time, only the core method $ () is obtained, and the call interface is tested in demo.
Var Zepto =(Function () {// variable initialization var $; var zepto ={}; var fragmentRE =/^ \ s * <(\ w + | !) [^>] *>/; Var singleTagRE =/^ <(\ w +) \ s * \/?> (?: <\/\ 1> |) $/; var tagExpanderRE =/<(?! Area | br | col | embed | hr | img | input | link | meta | param) ([\ w:] +) [^>] *) \/>/ig; var undefined; var emptyArray = []; var slice = emptyArray. slice; var cssNumber = {'column-count': 1, 'columns ': 1, 'font-weight': 1, 'Line-height': 1, 'opacity ': 1, 'z-Index': 1, 'zoom ': 1}; // var methodAttributes = ['val', 'css ', 'html ', 'text', 'data', 'width', 'height', 'offset ']; var table = document. createElemen T ('table'); var tableRow = document. createElement ('tr '); var containers = {'tr': document. createElement ('tbody'), 'tbody': table, 'thead': table, 'tfot': table, 'td ': tableRow, 'th': tableRow, '*': document. createElement ('div ')}; var readyRE =/complete | loaded | interactive/; var simpleSelectorRE =/^ [\ w-] * $/; var class2type = {}; var toString = class2type. toString; var isArray = Array. isArray | Function (object) {return object instanceof Array;}; function type (obj) {return obj = null? String (obj): class2type [toString. call (obj)] | "object";} function isFunction (value) {return type (value) = "function";} function isWindow (obj) {return obj! = Null & obj = obj. window;} function isDocument (obj) {return obj! = Null & obj. nodeType = obj. DOCUMENT_NODE;} function isObject (obj) {return type (obj) = "object";} function isPlainObject (obj) {return isObject (obj )&&! IsWindow (obj) & Object. getPrototypeOf (obj) = Object. prototype;} function likeArray (obj) {return typeof obj. length = 'number';} function dasherize (str) {return str. replace (/:/g ,'/'). replace (/([A-Z] +) ([A-Z] [a-z])/g, '$1 _ $2 '). replace (/([a-z \ d]) ([A-Z])/g, '$1 _ $2 '). replace (/_/g ,'-'). toLowerCase ()} function maybeAddPx (name, value) {return (typeof value = "number "&&! CssNumber [dasherize (name)])? Value + "px": value ;}/*** '$. Zepto. fragment requires an html string and an optional tag name to generate the dom generated by dom *. An array is returned. * This function can be overwritten by the plug-in * Not overwriting all browsers */zepto. fragment = function (html, name, properties) {var dom; var nodes; var container; // tags are specially processed if (singleTagRE. test (html) {dom = $ (document. createElement (RegExp. $1);} if (! Dom) {if (html. replace) {html = html. replace (tagExpanderRE, "<$1> </$2>");} if (name = undefined) {name = fragmentRE. test (html) & RegExp. $1;} if (! (Name in containers) {name = '*';} container = containers [name]; container. innerHTML = ''+ html; dom = $. each (slice. call (container. childNodes), function () {container. removeChild (this) ;});} if (isPlainObject (properties) {nodes =$ (dom); $. each (properties, function (key, value) {if (methodAttributes. indexOf (key)>-1) {nodes [key] (value);} else {nodes. attr (key, value) ;}}) ;}return dom ;}; /*** '$. Zepto. z' assigns the prototype of the given 'dom 'node array' $. note that '_ proto _' does not support Internet Explorer */Zepto. Z = function (dom, selector) {dom = dom | []; dom. _ proto _ = $. fn; dom. selector = selector | ''; return dom ;}; // '$. zepto. isz' checks that the given object is a Zepto set and can be overwritten by the plug-in. isZ = function (object) {return object instanceof zepto. z;};/*** '$. zepto. init 'is the jQuery reference for Zepto' $. fn. init '* uses the css selector and an optional context (to handle various special cases) * this method can be overwritten by the plug-in. */Zepto. init = function (selector, context) {// if not, an empty Zepto set if (! Selector) {return zepto. Z (); // check string type} else if (typeof selector = 'string') {selector = selector. trim ();/*** if it is an HTML clip, note that in chrome 21 and FF15 versions, * DOM error 12 is not set to <thrown */if (selector [0] = '<' & fragmentRE. test (selector) {dom = zepto. fragment (selector, RegExp. $1, context); selector = null;} // if a context exists, create a collection and select the node else if (context! = Undefined) {return $ (context ). find (selector);} // if it is a css selector, use it to select the node else {dom = zepto. qsa (document, selector) ;}// if a function exists, else if (isFunction (selector) {return $ (document) is triggered when domready is ready ). ready (selector);} // if zepto has been collected, else if (zepto. isZ (selector) {return selector;} else {// if the node is already an array, aggregate if (isArray (selector) {dom = compact (selector );} // wrap the DOM node else if (isObject (s Elector) {dom = [selector]; selector = null;} // if it is an HTML clip, create an else if (fragmentRE. test (selector) {dom = zepto. fragment (selector. trim (), RegExp. $1, context); selector = null;} // if a context exists, create a collection and select the else if (context! = Undefined) {return $ (context ). find (selector);} // if it is a css selector, use it to select the node else {dom = zepto. qsa (document, selector) ;}// create a new Zepto set return zepto for the detected node. Z (dom, selector );}; // '$' Is the meta object of Zepto. When '$' is called, this function is transferred to '$. zepto. init' for processing.$ = Function (selector, context) {return zepto. init (selector, context) ;};/*** '$. zepto. qsa' is the css selector of Zepto, which uses document. querySelectorAll and special case handling * can be overwritten by plug-ins */zepto. qsa = function (element, selector) {var found; var maybeID = (selector [0] = '#'); var maybeClass =! MaybeID & selector [0] = '.'; // confirm the name of the character after the subscript starts from 1 var nameOnly = maybeID | maybeClass? Selector. slice (1): selector; var isSimple = simpleSelectorRE. test (nameOnly); return (isDocument (element) & isSimple & maybeID )? (Found = element. getElementById (nameOnly ))? [Found]: []): (element. nodeType! = 1 & element. nodeType! = 9 )? []: Slice. call (isSimple &&! MaybeID )? MaybeClass? Element. getElementsByClassName (nameOnly): // class name element. getElementsByTagName (selector): // tag Name element. querySelectorAll (selector) // query all matched items);}; function setAttribute (node, name, value) {value = null? Node. removeAttribute (name): node. setAttribute (name, value);} // function parameter function funcArg (context, arg, idx, payload) {return isFunction (arg )? Arg. call (context, idx, payload): arg ;}$. type = type; $. isFunction = isFunction; $. isWindow = isWindow; $. isArray = isArray; $. isPlainObject = isPlainObject; // Zepto object iterator $. each = function (elements, callback) {var I; var key; if (likeArray (elements) {for (I = 0; I <elements. length; I ++) {if (callback. call (elements [I], I, elements [I]) === false) {return elements ;}} else {for (key in elements) {if (callback. call (elements [key], key, elements [key]) === false) {return elements ;}} return elements ;};// Configure the type ing $. each ("Boolean Number String Function Array Date RegExp Object Error ". split (""), function (I, name) {class2type ["[object" + name + "]"] = name. toLowerCase ();});/*** Defined method, applicable to all Zepto objects */$. fn = {slice: function () {return $ (slice. apply (this, arguments);}, ready: function (callback) {// check document. if (readyRE. test (document. readyState) & document. body) {callback ($);} else {document. addEventListener ('domainloaded', function () {callback ($) ;}, false) ;}, each: function (callback) {emptyArray. every. call (this, function (el, idx) {r Eturn callback. call (el, idx, el )! = False ;}); return this ;}, text: function (text) {return 0 in arguments? This. each (function (idx) {var newText = funcArg (this, text, idx, this. textContent); this. textContent = (newText = null )? '':'' + NewText;}): (0 in this? This [0]. textContent: null) ;}, attr: function (name, value) {var result; return (typeof name = 'string '&&! (1 in arguments ))? (! This. length | this [0]. nodeType! = 1? Undefined :(! (Result = this [0]. getAttribute (name) & name in this [0])? This [0] [name]: result): this. each (function (idx) {if (this. nodeType! = 1) {return;} if (isObject (name) {for (key in name) {setAttribute (this, key, name [key]);} else {setAttribute (this, name, funcArg (this, value, idx, this. getAttribute (name) ;}}) ;}, // css attribute settings css: function (property, value) {if (arguments. length <2) {var element = this [0]; var computedStyle = getComputedStyle (element, ''); if (! Element) {return;} if (typeof property = 'string') {return element. style [camelize (property)] | computedStyle. getPropertyValue (property);} else if (isArray (property) {var props ={}; $. each (isArray (property )? Property: [property], function (_, prop) {props [prop] = (element. style [camelize (prop)] | computedStyle. getPropertyValue (prop) ;}); return props ;}} var css = ''; if (type (property) = 'string') {if (! Value & value! = 0) {this. each (function () {this. style. removeProperty (dasherize (property);} else {css = dasherize (property) + ":" + maybeAddPx (property, value );}} else {for (key in property) {if (! Property [key] & property [key]! = 0) {this. each (function () {this. style. removeProperty (dasherize (key);} else {css + = dasherize (key) + ':' + maybeAddPx (key, property [key]) + '; ';}} return this. each (function () {this.style.css Text + = ';' + css;}) ;}; // inherits zepto. z. prototype = $. fn; // In '$. zepto 'namespace export internal API function zepto. uniq = uniq; zepto. deserializeValue = deserializeValue; $. zepto = zepto; return $;}) (); // global variable InterfaceWindow. Zepto = Zepto; window. $ == undefined & (window. $ = Zepto );
Example process: When we execute a $ ("# test"), the specific steps are as follows:
1. run zepto. init2. obtain this element, return an array, and then execute zepto. Z (dom, selector) 3. execute zepto on _ proto _ of the node list after array. z. prototype. Note zepto. z. prototype = $. fn, $. all methods under fn are attached to zepto. under prototype of Z, that is, $ ("# test") already has $. all methods of fn 4. returned array
Corresponding demo Page code: <! DOCTYPE html>
<Html>
<Head>
<Meta http-equiv = "X-UA-Compatible" content = "IE = Edge"/>
<Meta charset = "UTF-8"/>
<Title> Zepto source code analysis </title>
<Link rel = "stylesheet" href = "demo.css" type = "text/css"/>
</Head>
<Body>
<Div id = "test">
Test zepto source code
<Span class = "aa"> 22 </span>
<Span class = "aa"> 2332 </span>
</Div>
<Div class = "wrap"> content </div>
<Script src = "zepto-dev.js"> </script>
<Script>
Console. log ($ ('div '));
Console. log ($ ('. '));
Console. log ($ ('<div> This is the test content </div> '));
Console. log ($ ("<span/>", {text: "Test 111", id: "ceshi_111", css: {color: 'red '}}));
Zepto (function ($ ){
Console. log ('ready to Zepto! ');
});
</Script>
</Body>
</Html>
The final effect is as follows:
Linux source code analysis
Detailed analysis of linux TCP/IP stack code
1. Data Structure (msghdr, sk_buff, socket, sock, proto_ops, proto)
On the bsd socket layer, the operation object is socket, and data is stored in a data structure such as msghdr:
To create a socket, you must pass the family, type, and protocol parameters. To create a socket, you must create a socket instance, create a file descriptor structure, and establish some associations with each other, that is to say, establish a connection pointer and initialize these write and read operations on the file to map to the read and write Functions of the socket.
At the same time, initialize the socket operation function (proto_ops structure). If the input type parameter is of the STREAM type, it is initialized to SOCKET-> ops as inet_stream_ops. If it is of the DGRAM type, the SOCKET-ops is inet_dgram_ops. Inet_stream_ops is actually a struct that contains some entry functions for stream-type socket operations. In these functions, we mainly perform operations on the socket, at the same time, the socket-to-sock layer is passed by calling the related operations in sock mentioned below. For example, there is an inet_release operation in inet_stream_ops. In addition to the socket-Type Space release operation, this operation also calls the sock close operation of the socket connection. For the stream type, tcp_close to close sock
Release sock.
Create a socket and sock data space and initialize sock. the initialization process mainly involves initializing three queues, receive_queue (received data packet sk_buff linked list Queue ), send_queue (the sk_buff linked list queue for which data packets need to be sent), backlog_queue (mainly used for the packets whose three handshakes are successful and guessed by myself), and sock operations are initialized according to the family and type parameters, for example, if family is inet and type is stream, sock-> proto is initialized as tcp_prot. it includes the entry functions corresponding to the sock operation of the stream protocol.
When one end writes the socket, it first sorts the string buffer to be written into a msghdr data structure (see source code analysis of Linux kernel version 2.4 ), then, sock_sendmsg is called to transmit msghdr data to the inet layer. For each data packet in the data area of the msghdr structure, the sk_buff structure is created, the data is filled, and the data is mounted to the sending queue. Layer-by-layer protocol transfer. The Protocol at each layer does not copy data. Instead, perform operations on the sk_buff structure.
Reference: networking.ctocio.com.cn/tips/91/9385591.shtml
Help: webpage source code analysis
First, you are familiar with your own language. For example, C;
Secondly, you should be familiar with: HTML
You can get what you want based on the characteristics of the page.