1.將對象解析成字符串
function friendlyStringify(obj) {
if (typeof obj === 'object') {
if (Array.isArray(obj)) {
return '[' + obj.map(friendlyStringify).join(', ') + ']';
} else {
var pairs = [];
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
var keyEscaped = /^[a-z$_][\w$_]*$/i.test(key) ? key : JSON.stringify(key);
pairs.push(keyEscaped + ': ' + friendlyStringify(obj[key]));
}
}
return '{' + pairs.join(', ') + '}';
}
} else if (typeof obj === 'string') {
return JSON.stringify(obj);
} else if (typeof obj === 'function') {
return '[function object]';
}
// Differs from JSON.stringify in that undefined because undefined and that
// inf and nan don't become null
return String(obj);
}
? ?? ?首先對傳入?yún)?shù)的數(shù)據(jù)類型進行分析Object,String,Function。如果是Object判斷該Object是否為Array箩兽,如果是則遞歸遍歷其內(nèi)部的每一項。否則遍歷Object內(nèi)部的每一項將key和value做處理后存儲到數(shù)值pairs中坤按,并將pairs格式化為字符串返回死陆。
2.累積函數(shù)accumulateInto和accumulate
? ?? ?accumulate()函數(shù)將current與next進行拼接:
function accumulate(current, next) {
if (current == null) {
return next;
}
// Both are not empty. Warning: Never call x.concat(y) when you are not
// certain that x is an Array (x could be a string with concat method).
//數(shù)組拼接成一個新的數(shù)組(或隊列)
if (Array.isArray(current)) {
return current.concat(next);
}
if (Array.isArray(next)) {
return [current].concat(next);
}
// 非數(shù)組,則
return [current, next];
}
? ?? ?accumulateInto()函數(shù)將next寫入current數(shù)組中(或隊列里)
function accumulateInto(current, next) {
if (current == null) {
return next;
}
// Both are not empty. Warning: Never call x.concat(y) when you are not
// certain that x is an Array (x could be a string with concat method).
if (Array.isArray(current)) {
if (Array.isArray(next)) {
// 將next輸入寫入當(dāng)前數(shù)組中
current.push.apply(current, next);
return current;
}
current.push(next);
return current;
}
// current不是數(shù)組前联,next是數(shù)組
if (Array.isArray(next)) {
// A bit too dangerous to mutate `next`.
return [current].concat(next);
}
// 兩個都不是數(shù)組
return [current, next];
}
5.合成事件的函數(shù)
5.1獲取事件target
function getEventTarget(nativeEvent) {
// 兼容性問題
var target = nativeEvent.target || nativeEvent.srcElement || window;
// Normalize SVG <use> element events #4963
if (target.correspondingUseElement) {
target = target.correspondingUseElement;
}
// Safari may fire events on text nodes (Node.TEXT_NODE is 3).
// @see http://www.quirksmode.org/js/events_properties.html
return target.nodeType === 3 ? target.parentNode : target;
}
5.2阻止合成事件的默認事(SyntheticEvent.js中)
preventDefault: function () {
this.defaultPrevented = true;
var event = this.nativeEvent;
if (!event) {
return;
}
if (event.preventDefault) {
event.preventDefault();
// eslint-disable-next-line valid-typeof
} else if (typeof event.returnValue !== 'unknown') {
event.returnValue = false;
}
this.isDefaultPrevented = emptyFunction.thatReturnsTrue;
}
5.3 阻止合成事件冒泡
stopPropagation: function () {
var event = this.nativeEvent;
if (!event) {
return;
}
if (event.stopPropagation) {
event.stopPropagation();
} else if (typeof event.cancelBubble !== 'unknown') {
event.cancelBubble = true;
}
this.isPropagationStopped = emptyFunction.thatReturnsTrue;
}
5.4遍歷合成事件的事件隊列
@param arr 事件隊列
@param cb 事件執(zhí)行完后的回調(diào)函數(shù)
@param scope 定義域
function forEachAccumulated(arr, cb, scope) {
if (Array.isArray(arr)) {
arr.forEach(cb, scope);
} else if (arr) {
cb.call(scope, arr);
}
}
5.5 EventCharCode
獲取鍵盤字符,區(qū)分大小寫
function getEventCharCode(nativeEvent) {
var charCode;
var keyCode = nativeEvent.keyCode;
if ('charCode' in nativeEvent) {
charCode = nativeEvent.charCode;
// FF does not set `charCode` for the Enter-key, check against `keyCode`.
if (charCode === 0 && keyCode === 13) {
charCode = 13;
}
} else {
// IE8 does not implement `charCode`, but `keyCode` has the correct value.
charCode = keyCode;
}
// Some non-printable keys are reported in `charCode`/`keyCode`, discard them.
// Must not discard the (non-)printable Enter-key.
if (charCode >= 32 || charCode === 13) {
return charCode;
}
return 0;
}
5.6遍歷所有的祖先節(jié)點
var ancestor = targetInst;
do {
bookKeeping.ancestors.push(ancestor);
ancestor = ancestor && findParent(ancestor);
} while (ancestor);
向上尋找父節(jié)點的方法findParent
function findParent(inst) {
// TODO: It may be a good idea to cache this to prevent unnecessary DOM
// traversal, but caching is difficult to do correctly without using a
// mutation observer to listen for all DOM changes.
while (inst._hostParent) {
inst = inst._hostParent;
}
var rootNode = ReactDOMComponentTree.getNodeFromInstance(inst);
var container = rootNode.parentNode;
return ReactDOMComponentTree.getClosestInstanceFromNode(container);
}