prototype 1.3.1 版本和之前的 1.2.0 版本有了不少改进,并增加了新的功能:

1. 增加了事件注册管理
2. 增加了空间定位的常用函数
3. 改善了 xmlhttp 的封装
4. 移除了 Effect.js,交给 Rico 或者 script.aculo.us 这些扩展库类实现。
5. bug 修复
代码:

var Prototype = {
Version: '1.3.1',
// 一个空方法,其后的代码常会用到,先前的版本该方法被定义于 Ajax 类中。
emptyFunction: function() {}
}

var Class = {
create: function() {
  return function() {
    this.initialize.apply(this, arguments);
  }
}
}

var Abstract = new Object();

Object.extend = function(destination, source) {
for (property in source) {
  destination[property] = source[property];
}
return destination;
}

Object.prototype.extend = function(object) {
return Object.extend.apply(this, [this, object]);
}

Function.prototype.bind = function(object) {
var __method = this;
return function() {
  __method.apply(object, arguments);
}
}

Function.prototype.bindAsEventListener = function(object) {
var __method = this;
return function(event) {
  __method.call(object, event || window.event);
}
}

Number.prototype.toColorPart = function() {
var digits = this.toString(16);
if (this < 16) return '0' + digits;
return digits;
}

var Try = {
these: function() {
  var returnValue;

for (var i = 0; i < arguments.length; i++) {
    var lambda = arguments[i];
    try {
    returnValue = lambda();
    break;
    } catch (e) {}
  }

return returnValue;
}
}

var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
initialize: function(callback, frequency) {
  this.callback = callback;
  this.frequency = frequency;
  this.currentlyExecuting = false;
  this.registerCallback();
},

registerCallback: function() {
  setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},

onTimerEvent: function() {
  if (!this.currentlyExecuting) {
    try {
    this.currentlyExecuting = true;
    this.callback();
    } finally {
    this.currentlyExecuting = false;
    }
  }
}
}

function $() {
var elements = new Array();

for (var i = 0; i < arguments.length; i++) {
  var element = arguments[i];
  if (typeof element == 'string')
    element = document.getElementByIdx(element);

if (arguments.length == 1)
    return element;

elements.push(element);
}

return elements;
}

if (!Array.prototype.push) {
Array.prototype.push = function() {
    var startLength = this.length;
    for (var i = 0; i < arguments.length; i++)
    this[startLength + i] = arguments[i];
  return this.length;
}
}

if (!Function.prototype.apply) {
// Based on code from [url]http://www.youngpup.net/[/url]
Function.prototype.apply = function(object, parameters) {
  var parameterStrings = new Array();
  if (!object)   object = window;
  if (!parameters) parameters = new Array();
 
  for (var i = 0; i < parameters.length; i++)
    parameterStrings[i] = 'parameters[' + i + ']';
 
  object.__apply__ = this;
  var result = eval_r('object.__apply__(' +
    parameterStrings.join(', ') + ')');
  object.__apply__ = null;
 
  return result;
}
}

String.prototype.extend({

stripTags: function() {
  return this.replace(/<\/?[^>]+>/gi, '');
},

escapeHTML: function() {
  var div = document.createElement('div');
  var text = document.createTextNode(this);
  div.appendChild(text);
  return div.innerHTML;
},
 
unescapeHTML: function() {
  var div = document.createElement('div');
  div.innerHTML = this.stripTags();
  return div.childNodes[0].nodeValue;
}
});

var Ajax = {
getTransport: function() {
  return Try.these(
    function() {return new ActiveXObject('Msxml2.XMLHTTP')},
    function() {return new ActiveXObject('Microsoft.XMLHTTP')},
    function() {return new XMLHttpRequest()}
  ) || false;
}
}

Ajax.Base = function() {};
Ajax.Base.prototype = {

setOptions: function(options) {
  this.options = {
    method:     'post',
    asynchronous: true,
    parameters:   ''
  }.extend(options || {});
},

responseIsSuccess: function() {
  return this.transport.status == undefined
    || this.transport.status == 0
    || (this.transport.status >= 200 && this.transport.status < 300);
},

responseIsFailure: function() {
  return !this.responseIsSuccess();
}
}

Ajax.Request = Class.create();

Ajax.Request.Events =
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];

Ajax.Request.prototype = (new Ajax.Base()).extend({
initialize: function(url, options) {
  this.transport = Ajax.getTransport();
  this.setOptions(options);
  this.request(url);
},

 
request: function(url) {
  var parameters = this.options.parameters || '';
  if (parameters.length > 0) parameters += '&_=';

try {
    if (this.options.method == 'get')
    url += '?' + parameters;

this.transport.open(this.options.method, url,
    this.options.asynchronous);

if (this.options.asynchronous) {
    this.transport.onreadystatechange = this.onStateChange.bind(this);
    setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
    }

this.setRequestHeaders();

var body = this.options.postBody ? this.options.postBody : parameters;
    this.transport.send(this.options.method == 'post' ? body : null);

} catch (e) {
  }
},

setRequestHeaders: function() {
  var requestHeaders =
    ['X-Requested-With', 'XMLHttpRequest',
    'X-Prototype-Version', Prototype.Version];

if (this.options.method == 'post') {
    requestHeaders.push('Content-type',
    'application/x-www-form-urlencoded');

if (this.transport.overrideMimeType)
    requestHeaders.push('Connection', 'close');
  }

if (this.options.requestHeaders)
    requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);

for (var i = 0; i < requestHeaders.length; i += 2)
    this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
},

onStateChange: function() {
  var readyState = this.transport.readyState;
 
  if (readyState != 1)
    this.respondToReadyState(this.transport.readyState);
},

respondToReadyState: function(readyState) {
  var event = Ajax.Request.Events[readyState];

if (event == 'Complete')
    (this.options['on' + this.transport.status]
    || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
    || Prototype.emptyFunction)(this.transport);

(this.options['on' + event] || Prototype.emptyFunction)(this.transport);

if (event == 'Complete')
    this.transport.onreadystatechange = Prototype.emptyFunction;
}
});

Ajax.Updater = Class.create();
Ajax.Updater.ScriptFragment = '(?:<script.*?>)((\n|.)*?)(?:<\/script>)';

Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
initialize: function(container, url, options) {

this.containers = {
    success: container.success ? $(container.success) : $(container),
    failure: container.failure ? $(container.failure) :
    (container.success ? null : $(container))
  }

this.transport = Ajax.getTransport();
  this.setOptions(options);

var onComplete = this.options.onComplete || Prototype.emptyFunction;
  this.options.onComplete = (function() {
    this.updateContent();
    onComplete(this.transport);
  }).bind(this);

this.request(url);
},

updateContent: function() {
  var receiver = this.responseIsSuccess() ?
    this.containers.success : this.containers.failure;

var match   = new RegExp(Ajax.Updater.ScriptFragment, 'img');
  var response = this.transport.responseText.replace(match, '');
  var scripts = this.transport.responseText.match(match);

if (receiver) {
    if (this.options.insertion) {
    new this.options.insertion(receiver, response);
    } else {
    receiver.innerHTML = response;
    }
  }

if (this.responseIsSuccess()) {
    if (this.onComplete)
    setTimeout((function() {this.onComplete(
      this.transport)}).bind(this), 10);
  }

if (this.options.evalScripts && scripts) {
 
    match = new RegExp(Ajax.Updater.ScriptFragment, 'im');
    setTimeout((function() {
    for (var i = 0; i < scripts.length; i++)
      eval_r(scripts[i].match(match)[1]);
    }).bind(this), 10);
  }
}
});

Ajax.PeriodicalUpdater = Class.create();
Ajax.PeriodicalUpdater.prototype = (new Ajax.Base()).extend({
initialize: function(container, url, options) {
  this.setOptions(options);
  this.onComplete = this.options.onComplete;

this.frequency = (this.options.frequency || 2);
  // decay 可能是一个时间调整因素
  this.decay = 1;

this.updater = {};
  this.container = container;
  this.url = url;

this.start();
},

start: function() {
  this.options.onComplete = this.updateComplete.bind(this);
  this.onTimerEvent();
},

stop: function() {
  this.updater.onComplete = undefined;
  clearTimeout(this.timer);
  (this.onComplete || Ajax.emptyFunction).apply(this, arguments);
},

updateComplete: function(request) {
  if (this.options.decay) {
    this.decay = (request.responseText == this.lastText ?
    this.decay * this.options.decay : 1);

this.lastText = request.responseText;
  }
  this.timer = setTimeout(this.onTimerEvent.bind(this),
    this.decay * this.frequency * 1000);
},

onTimerEvent: function() {
  this.updater = new Ajax.Updater(this.container, this.url, this.options);
}
});

document.getElementsByClassName = function(className) {
var children = document.getElementsByTagName_r('*') || document.all;
var elements = new Array();

for (var i = 0; i < children.length; i++) {
  var child = children[i];
  var classNames = child.className.split(' ');
  for (var j = 0; j < classNames.length; j++) {
    if (classNames[j] == className) {
    elements.push(child);
    break;
    }
  }
}

return elements;
}

if (!window.Element) {
var Element = new Object();
}

Object.extend(Element, {

toggle: function() {
  for (var i = 0; i < arguments.length; i++) {
    var element = $(arguments[i]);
    element.style.display =
    (element.style.display == 'none' ? '' : 'none');
  }
},

hide: function() {
  for (var i = 0; i < arguments.length; i++) {
    var element = $(arguments[i]);
    element.style.display = 'none';
  }
},

show: function() {
  for (var i = 0; i < arguments.length; i++) {
    var element = $(arguments[i]);
    element.style.display = '';
  }
},

remove: function(element) {
  element = $(element);
  element.parentNode.removeChild(element);
},
 
getHeight: function(element) {
  element = $(element);
  return element.offsetHeight;
},

hasClassName: function(element, className) {
  element = $(element);
  if (!element)
    return;
  var a = element.className.split(' ');
  for (var i = 0; i < a.length; i++) {
    if (a[i] == className)
    return true;
  }
  return false;
},

addClassName: function(element, className) {
  element = $(element);
  Element.removeClassName(element, className);
  element.className += ' ' + className;
},

removeClassName: function(element, className) {
  element = $(element);
  if (!element)
    return;
  var newClassName = '';
  var a = element.className.split(' ');
  for (var i = 0; i < a.length; i++) {
    if (a[i] != className) {
    if (i > 0)
      newClassName += ' ';
    newClassName += a[i];
    }
  }
  element.className = newClassName;
},

// removes whitespace-only text node children
cleanWhitespace: function(element) {
  var element = $(element);
  for (var i = 0; i < element.childNodes.length; i++) {
    var node = element.childNodes[i];
    if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
    Element.remove(node);
  }
}
});

var Toggle = new Object();
Toggle.display = Element.toggle;

Abstract.Insertion = function(adjacency) {
this.adjacency = adjacency;
}

Abstract.Insertion.prototype = {
initialize: function(element, content) {
  this.element = $(element);
  this.content = content;
 
  if (this.adjacency && this.element.insertAdjacentHTML) {
    this.element.insertAdjacentHTML(this.adjacency, this.content);
  } else {
   
    this.range = this.element.ownerDocument.createRange();
 
    if (this.initializeRange) this.initializeRange();
    this.fragment = this.range.createContextualFragment(this.content);
 
    this.insertContent();
  }
}
}

var Insertion = new Object();

Insertion.Before = Class.create();
Insertion.Before.prototype = (new Abstract.Insertion('beforeBegin')).extend({
initializeRange: function() {
  this.range.setStartBefore(this.element);
},

insertContent: function() {
  this.element.parentNode.insertBefore(this.fragment, this.element);
}
});

Insertion.Top = Class.create();
Insertion.Top.prototype = (new Abstract.Insertion('afterBegin')).extend({
initializeRange: function() {
  this.range.selectNodeContents(this.element);
  this.range.collapse(true);
},

insertContent: function() {
  this.element.insertBefore(this.fragment, this.element.firstChild);
}
});

Insertion.Bottom = Class.create();
Insertion.Bottom.prototype = (new Abstract.Insertion('beforeEnd')).extend({
initializeRange: function() {
  this.range.selectNodeContents(this.element);
  this.range.collapse(this.element);
},

insertContent: function() {
  this.element.appendChild(this.fragment);
}
});

Insertion.After = Class.create();
Insertion.After.prototype = (new Abstract.Insertion('afterEnd')).extend({
initializeRange: function() {
  this.range.setStartAfter(this.element);
},

insertContent: function() {
  this.element.parentNode.insertBefore(this.fragment,
    this.element.nextSibling);
}
});

var Field = {

clear: function() {
  for (var i = 0; i < arguments.length; i++)
    $(arguments[i]).value = '';
},

focus: function(element) {
  $(element).focus();
},
 
present: function() {
  for (var i = 0; i < arguments.length; i++)
    if ($(arguments[i]).value == '') return false;
  return true;
},

select: function(element) {
  $(element).select();
},

activate: function(element) {
  $(element).focus();
  $(element).select();
}
}

var Form = {

serialize: function(form) {
  var elements = Form.getElements($(form));
  var queryComponents = new Array();
 
  for (var i = 0; i < elements.length; i++) {
    var queryComponent = Form.Element.serialize(elements[i]);
    if (queryComponent)
    queryComponents.push(queryComponent);
  }
 
  return queryComponents.join('&');
},

getElements: function(form) {
  var form = $(form);
  var elements = new Array();

for (tagName in Form.Element.Serializers) {
    var tagElements = form.getElementsByTagName_r(tagName);
    for (var j = 0; j < tagElements.length; j++)
    elements.push(tagElements[j]);
  }
  return elements;
},

getInputs: function(form, typeName, name) {
  var form = $(form);
  var inputs = form.getElementsByTagName_r('input');
 
  if (!typeName && !name)
    return inputs;
   
  var matchingInputs = new Array();
  for (var i = 0; i < inputs.length; i++) {
    var input = inputs[i];
    if ((typeName && input.type != typeName) ||
      (name && input.name != name))
    continue;
    matchingInputs.push(input);
  }

return matchingInputs;
},

disable: function(form) {
  var elements = Form.getElements(form);
  for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    element.blur();
    element.disabled = 'true';
  }
},

enable: function(form) {
  var elements = Form.getElements(form);
  for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    element.disabled = '';
  }
},

focusFirstElement: function(form) {
  var form = $(form);
  var elements = Form.getElements(form);
  for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    if (element.type != 'hidden' && !element.disabled) {
    Field.activate(element);
    break;
    }
  }
},

reset: function(form) {
  $(form).reset();
}
}

Form.Element = {

serialize: function(element) {
  var element = $(element);
  var method = element.tagName.toLowerCase();
  var parameter = Form.Element.Serializers[method](element);
 
  if (parameter)
    return encodeURIComponent(parameter[0]) + '=' +
    encodeURIComponent(parameter[1]);            
},

getValue: function(element) {
  var element = $(element);
  var method = element.tagName.toLowerCase();
  var parameter = Form.Element.Serializers[method](element);
 
  if (parameter)
    return parameter[1];
}
}

Form.Element.Serializers = {
input: function(element) {
  switch (element.type.toLowerCase()) {
    case 'submit':
    case 'hidden':
    case 'password':
    case 'text':
    return Form.Element.Serializers.textarea(element);
    case 'checkbox':
    case 'radio':
    return Form.Element.Serializers.inputSelector(element);
  }
  return false;
},

inputSelector: function(element) {
  if (element.checked)
    return [element.name, element.value];
},

textarea: function(element) {
  return [element.name, element.value];
},

select: function(element) {
  var value = '';
  if (element.type == 'select-one') {
    var index = element.selectedIndex;
    if (index >= 0)
    value = element.options[index].value || element.options[index].text;
  } else {

value = new Array();
    for (var i = 0; i < element.length; i++) {
    var opt = element.options[i];
    if (opt.selected)
      value.push(opt.value || opt.text);
    }
  }
  return [element.name, value];
}
}

var $F = Form.Element.getValue;

Abstract.TimedObserver = function() {}

Abstract.TimedObserver.prototype = {
initialize: function(element, frequency, callback) {
  this.frequency = frequency;
  this.element   = $(element);
  this.callback = callback;
 
  this.lastValue = this.getValue();
  this.registerCallback();
},

registerCallback: function() {
  setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},

onTimerEvent: function() {
  var value = this.getValue();
  if (this.lastValue != value) {
    this.callback(this.element, value);
    this.lastValue = value;
  }
}
}

Form.Element.Observer = Class.create();
Form.Element.Observer.prototype = (new Abstract.TimedObserver()).extend({
getValue: function() {
  return Form.Element.getValue(this.element);
}
});

Form.Observer = Class.create();
Form.Observer.prototype = (new Abstract.TimedObserver()).extend({
getValue: function() {
  return Form.serialize(this.element);
}
});

Abstract.EventObserver = function() {}
Abstract.EventObserver.prototype = {
initialize: function(element, callback) {
  this.element = $(element);
  this.callback = callback;
 
  this.lastValue = this.getValue();
  if (this.element.tagName.toLowerCase() == 'form')
    this.registerFormCallbacks();
  else
    this.registerCallback(this.element);
},

onElementEvent: function() {
  var value = this.getValue();
  if (this.lastValue != value) {
    this.callback(this.element, value);
    this.lastValue = value;
  }
},

registerFormCallbacks: function() {
  var elements = Form.getElements(this.element);
  for (var i = 0; i < elements.length; i++)
    this.registerCallback(elements[i]);
},

registerCallback: function(element) {
  if (element.type) {
    switch (element.type.toLowerCase()) {
   
    case 'checkbox':
    case 'radio':
      element.target = this;
      element.prev_onclick = element.onclick || Prototype.emptyFunction;
   
      element.onclick = function() {
        this.prev_onclick();
        this.target.onElementEvent();
      }
      break;

case 'password':
    case 'text':
    case 'textarea':
    case 'select-one':
    case 'select-multiple':
      element.target = this;
      element.prev_onchange = element.onchange || Prototype.emptyFunction;
      element.onchange = function() {
        this.prev_onchange();
        this.target.onElementEvent();
      }
      break;
    }
  }  
}
}

Form.Element.EventObserver = Class.create();
Form.Element.EventObserver.prototype = (new Abstract.EventObserver()).extend({
getValue: function() {
  return Form.Element.getValue(this.element);
}
});

Form.EventObserver = Class.create();
Form.EventObserver.prototype = (new Abstract.EventObserver()).extend({
getValue: function() {
  return Form.serialize(this.element);
}
});

if (!window.Event) {
var Event = new Object();
}

Object.extend(Event, {
KEY_BACKSPACE: 8,
KEY_TAB:     9,
KEY_RETURN:   13,
KEY_ESC:     27,
KEY_LEFT:   37,
KEY_UP:     38,
KEY_RIGHT:   39,
KEY_DOWN:   40,
KEY_DELETE:   46,

element: function(event) {
  return event.target || event.srcElement;
},

isLeftClick: function(event) {
  return (((event.which) && (event.which == 1)) ||
        ((event.button) && (event.button == 1)));
},

pointerX: function(event) {
  return event.pageX || (event.clientX +
    (document.documentElement.scrollLeft || document.body.scrollLeft));
},

pointerY: function(event) {
  return event.pageY || (event.clientY +
    (document.documentElement.scrollTop || document.body.scrollTop));
},

stop: function(event) {
  if (event.preventDefault) {
    event.preventDefault();
    event.stopPropagation();
  } else {
    event.returnValue = false;
  }
},
// find the first node with the given tagName, starting from the
// node the event was triggered on; traverses the DOM upwards

findElement: function(event, tagName) {
  var element = Event.element(event);
  while (element.parentNode && (!element.tagName ||
    (element.tagName.toUpperCase() != tagName.toUpperCase())))
    element = element.parentNode;
  return element;
},

observers: false,
 
_observeAndCache: function(element, name, observer, useCapture) {
  if (!this.observers) this.observers = [];
  if (element.addEventListener) {
    this.observers.push([element, name, observer, useCapture]);
    element.addEventListener(name, observer, useCapture);
  } else if (element.attachEvent) {
    this.observers.push([element, name, observer, useCapture]);
    element.attachEvent('on' + name, observer);
  }
},

unloadCache: function() {
  if (!Event.observers) return;
  for (var i = 0; i < Event.observers.length; i++) {
 
    Event.stopObserving.apply(this, Event.observers[i]);
    Event.observers[i][0] = null;
  }
  Event.observers = false;
},

observe: function(element, name, observer, useCapture) {
  var element = $(element);
  useCapture = useCapture || false;
 
  if (name == 'keypress' &&
    ((navigator.appVersion.indexOf('AppleWebKit') > 0)
    || element.attachEvent))
    name = 'keydown';
 
  this._observeAndCache(element, name, observer, useCapture);
},

stopObserving: function(element, name, observer, useCapture) {
  var element = $(element);
  useCapture = useCapture || false;
 
  if (name == 'keypress' &&
    ((navigator.appVersion.indexOf('AppleWebKit') > 0)
    || element.detachEvent))
    name = 'keydown';
 
  if (element.removeEventListener) {
    element.removeEventListener(name, observer, useCapture);
  } else if (element.detachEvent) {
    element.detachEvent('on' + name, observer);
  }
}
});

Event.observe(window, 'unload', Event.unloadCache, false);

var Position = {

// set to true if needed, warning: firefox performance problems
// NOT neeeded for page scrolling, only if draggable contained in
// scrollable elements
includeScrollOffsets: false,

// must be called before calling withinIncludingScrolloffset, every time the
// page is scrolled
prepare: function() {
  this.deltaX = window.pageXOffset
          || document.documentElement.scrollLeft
          || document.body.scrollLeft
          || 0;
  this.deltaY = window.pageYOffset

|| document.documentElement.scrollTop
          || document.body.scrollTop
          || 0;
},

realOffset: function(element) {
  var valueT = 0, valueL = 0;
  do {
    valueT += element.scrollTop || 0;
    valueL += element.scrollLeft || 0;
    element = element.parentNode;
  } while (element);
  return [valueL, valueT];
},

cumulativeOffset: function(element) {
  var valueT = 0, valueL = 0;
  do {
    valueT += element.offsetTop || 0;
    valueL += element.offsetLeft || 0;
    element = element.offsetParent;
  } while (element);
  return [valueL, valueT];
},

// caches x/y coordinate pair to use with overlap

within: function(element, x, y) {
  if (this.includeScrollOffsets)
    return this.withinIncludingScrolloffsets(element, x, y);
  this.xcomp = x;
  this.ycomp = y;
  this.offset = this.cumulativeOffset(element);
  return (y >= this.offset[1] &&
        y < this.offset[1] + element.offsetHeight &&
        x >= this.offset[0] &&
        x < this.offset[0] + element.offsetWidth);
},
withinIncludingScrolloffsets: function(element, x, y) {
  var offsetcache = this.realOffset(element);
  this.xcomp = x + offsetcache[0] - this.deltaX;
  this.ycomp = y + offsetcache[1] - this.deltaY;
  this.offset = this.cumulativeOffset(element);
  return (this.ycomp >= this.offset[1] &&
        this.ycomp < this.offset[1] + element.offsetHeight &&
        this.xcomp >= this.offset[0] &&
        this.xcomp < this.offset[0] + element.offsetWidth);
},
// within must be called directly before

overlap: function(mode, element) {
  if (!mode) return 0;
  if (mode == 'vertical')
    return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
    element.offsetHeight;
  if (mode == 'horizontal')
    return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
    element.offsetWidth;
},

clone: function(source, target) {
  source = $(source);
  target = $(target);
  target.style.position = 'absolute';
  var offsets = this.cumulativeOffset(source);
  target.style.top   = offsets[1] + 'px';
  target.style.left   = offsets[0] + 'px';
  target.style.width = source.offsetWidth + 'px';
  target.style.height = source.offsetHeight + 'px';
}
}

 

prototype.js源码的更多相关文章

  1. prototype.js 源码解读(02)

    如果你想研究一些比较大型的js框架的源码的话,本人建议你从其最初的版本开始研读,因为最初的版本东西少,易于研究,而后的版本基本都是在其基础上不断扩充罢了,所以,接下来我不准备完全解读prototype ...

  2. prototype.js 源码解读(01)

    prototype.js是一个设计的非常优雅且很有实用价值的js基础类库,其源码非常值得研究.研究它的源码不仅能提升个人水平,而且对你打下坚实的js基础也很有帮助.因本人技术水平有限,该解读仅供参考. ...

  3. MVVM架构~knockoutjs系列之从Knockout.Validation.js源码中学习它的用法

    返回目录 说在前 有时,我们在使用一个插件时,在网上即找不到它的相关API,这时,我们会很抓狂的,与其抓狂,还不如踏下心来,分析一下它的源码,事实上,对于JS这种开发语言来说,它开发的插件的使用方法都 ...

  4. underscore.js 源码

    underscore.js 源码 underscore]JavaScript 中如何判断两个元素是否 "相同" Why underscore 最近开始看 underscore.js ...

  5. 从template到DOM(Vue.js源码角度看内部运行机制)

    写在前面 这篇文章算是对最近写的一系列Vue.js源码的文章(https://github.com/answershuto/learnVue)的总结吧,在阅读源码的过程中也确实受益匪浅,希望自己的这些 ...

  6. Vue.js源码——事件机制

    写在前面 因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出.文章的原地址:https://github.com/an ...

  7. 从Vue.js源码角度再看数据绑定

    写在前面 因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出.文章的原地址:https://github.com/an ...

  8. Underscore.js 源码学习笔记(下)

    上接 Underscore.js 源码学习笔记(上) === 756 行开始 函数部分. var executeBound = function(sourceFunc, boundFunc, cont ...

  9. Underscore.js 源码学习笔记(上)

    版本 Underscore.js 1.9.1 一共 1693 行.注释我就删了,太长了… 整体是一个 (function() {...}());  这样的东西,我们应该知道这是一个 IIFE(立即执行 ...

随机推荐

  1. JAVA学习博客---2015-6

    JAVA核心技术卷一第一遍看得差不多了,应该是五月初开始看的,用了两个月的中午时间看完的,一共七百多页,接下来还是需要再看一遍,不懂的还是有很多. JAVA和C++一样是面向对象OOP的语言,不同于命 ...

  2. 使用Vs2012开发Metro时在另一台win8平板上调试的步骤

    需求:开发一个metro应用,因为要给平面设计师参谋, 需要将软件安装在win8平板上. 环境:开发机是win8,  win8平板是win8.1rtm , 是用老的win7平板改装的. 步骤: 1:拷 ...

  3. Knockoutjs 实践入门 (3) 绑定数组

    <form id="form1" runat="server">        <div>            <!--text ...

  4. 使用Guava提供的transform批量转换

    实际开发了,为了快速查询,我们会把日期以Long类型的方式存储到数据库中,比如20000000000000L,但显示的时候,要完整的日期,即yyyy-MM-dd的格式显示. 这个时候,我们就可以使用C ...

  5. 在ThoughtWorks工作这几年我学到了什么?

    不知不觉,从2012年5月1日加入ThoughtWorks到现在,已经3年有余了.时间过得很快,这三年多我干了很多事情,但仔细想想也没有什么特别值得一提的.在一个公司呆久了总觉得很多事情是理所当然的, ...

  6. NanoProfiler - 适合生产环境的性能监控类库 之 大数据篇

    上期回顾 上一期:NanoProfiler - 适合生产环境的性能监控类库 之 基本功能篇 上次介绍了NanoProfiler的基本功能,提到,NanoProfiler实现了MiniProfiler欠 ...

  7. EF架构~二级域名中共享Session

    回到目录 对于一个有点规模的网站,都会有各个子网站,说是子网站,其实也都是独立的站点,一般通过二次域名来分开,如www.zzl.com,它可以有很多子网站,如image.zzl.com,file.zz ...

  8. Atitit 发帖机系列(7) 词法分析的方法attilax大总结)

    Atitit 发帖机系列(7) 词法分析的方法attilax大总结) 1.1. 词法分析貌似俩大方法,一个直接根据状态图转换,一个根据dfa1 1.2. switchcase或者ifelse 最原始方 ...

  9. Atitit Immutability 和final的优点

    Atitit Immutability 和final的优点 什么是 immutability? 其实细分起来有语法上的 immutable (例如 Java 里的 final 关键字), 和运行时对象 ...

  10. 大数据时代的IT架构设计

    大数据时代的IT架构设计(来自互联网.银行等领域的一线架构师先进经验分享) IT架构设计研究组 编著   ISBN 978-7-121-22605-2 2014年4月出版 定价:49.00元 208页 ...