ホームページ > 記事 > ウェブフロントエンド > jsフレームワークのソースコード調査
【はじめに】Underscore js のソースコード Underscore js はネイティブ JavaScript オブジェクトを拡張するのではなく、_() メソッドを呼び出してカプセル化します。カプセル化が完了すると、ネイティブ JavaScript オブジェクトは Underscore オブジェクトになります。指定された変数がオブジェクトであるかどうかを判断します
Underscore.js
はネイティブの JavaScript
オブジェクトを拡張しませんが、_( )
メソッドを使用してカプセル化します。カプセル化が完了すると、ネイティブの JavaScript
オブジェクトは Underscore
オブジェクトになります。 Underscore.js
没有对原生 JavaScript
对象进行扩展,而是通过调用 _()
方法进行封装,一旦封装完成,原生 JavaScript
对象便成为一个 Underscore
对象。
// Is a given variable an object? _.isObject = function(obj) { var type = typeof obj; return type === 'function' || type === 'object' && !!obj; };
这是underscore.js
的判断给定变量是否是object
的一段源码。 我们知道typeof
会返回如下六个值:
1. 'undefined' --- 这个值未定义;2. 'boolean' --- 这个值是布尔值;3. 'string' --- 这个值是字符串;4. 'number' --- 这个值是数值;5. 'object' --- 这个值是对象或null;6. 'function' --- 这个值是函数。
而&&
的优先级要高与||
。!!
的作用相当于Boolean()
,将其转换为布尔值。
// Is a given value a DOM element? _.isElement = function(obj) { return !!(obj && obj.nodeType === 1); };
同样!!
相当于Boolean()
的作用,nodeType === 1
则说明是元素节点,属性attr
是2 ,文本text
是3
<body> <p id="test">测试</p><script> var t = document.getElementById('test'); alert(t.nodeType);//1 alert(t.nodeName);//p alert(t.nodeValue);//null</script></body>
firstChild
属性
var t = document.getElementById('test').firstChild; alert(t.nodeType);//3alert(t.nodeName);//#testalert(t.nodeValue);//测试
文本节点也算是一个节点,所以p的子节点是文本节点,所以返回3
isArray = Array.isArray || function(object){ return object instanceof Array }
Array.isArray()
方法:如果一个对象是数组就返回true
,如果不是则返回false
。
instanceof
用于判断一个变量是否某个对象的实例,如
var a= []; alert(a instanceof Array);//返回 true
同时 alert(a instanceof Object)
也会返回 true
isArray
返回布尔值,如果Array.isArray
为true
,则返回true
,否则返回object instanceof Array
的结果。
class2type = {},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" }
class2type
是一个空对象,实际上一个什么都没有的空对象是这样创建的Object.create(null);
我们可以通过Object.prototype.toString.call()
方法来判断数据类型,例如:
console.log(Object.prototype.toString.call(123)) //[object Number] console.log(Object.prototype.toString.call('123')) //[object String] console.log(Object.prototype.toString.call(undefined)) //[object Undefined] console.log(Object.prototype.toString.call(true)) //[object Boolean] console.log(Object.prototype.toString.call({})) //[object Object] console.log(Object.prototype.toString.call([])) //[object Array] console.log(Object.prototype.toString.call(function(){})) //[object Function]
首先如果参数obj
是undefined
或null
,则通过String(obj)
转换为对应的原始字符串“undefined
”或“null
”。
然后class2type[toString.call(obj)]
首先借用Object
的原型方法toString()
来获取obj
的字符串表示,返回值的形式是 [object class]
,其中的class
是内部对象类。
然后从对象class2type
中取出[object class]
对应的小写字符串并返回;如果未取到则一律返回“object
。
get: function(idx){ return idx === undefined ? slice.call(this) : this[idx >= 0 ? idx : idx + this.length] },
取集合中对应指定索引的值,如果idx
小于0,则idx
等于idx+length
,length
为集合的长度.
可能你刚看到slice.call(this)
会觉得很纳闷,其实不仅是zepto.js
的源码,包括jQuery
,backbone
的源码都是这么写的,只不过它们在最开头做了声明:
var push = array.push;var slice = array.slice;var splice = array.splice;
所以slice.call(this)
其实还是Array.slce.call(this)
//为对象添加 class 属性值 addClassName: function(element, className) { element = $(element); Element.removeClassName(element, className); element.className += ' ' + className; }, //为对象移除 class 属性值 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; },
因为addClassName
依赖于removeClassName()
,所以先分析后者,$()
是先将元素封装成prototype
对象,
if(!element) return
这句的意思就是如果元素对象不存在,则忽略不再继续执行的意思,也就是终止的意思。
split() 方法用于把一个字符串分割成字符串数组。
如果把空字符串 (""
) 用作 分隔符,那么 该对象 中的每个字符之间都会被分割。
//是否拥有 class 属性值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;//返回错误的处理结果},
/** * 为兼容旧版本的浏览器增加 Array 的 push 方法。 */if (!Array.prototype.push) { Array.prototype.push = function() { var startLength = this.length;//this指代Array for (var i = 0; i < arguments.length; i++) this[startLength + i] = arguments[i];//this依旧指代Array return this.length; } }
!Array.prototype.push
如果为true
,说明浏览器不支持该方法,则往下执行。this[startLength + i] = arguments[i]
将传递进来的每个参数依次放入数组中,最后返回数组的长度
访问对象可以使用(.)
表示法,也可以使用[]
来访问,同样访问数组元素也是
jQuery
源码太多关联了,所以不好单独拿出来做分析,就举一两个简单的例子吧:
jQuery.prototype = { toArray: function() { return slice.call( this ); }, }
Array.prototype.slice.call(arguments)
能将具有length
属性的对象转成数组,也就是说其目的是将arguments
对象的数组提出来转化为数组。例如:
<script> var a = {length:4,0:'zero',1:'one',2:'two'}; console.log(Array.prototype.slice.call(a));// Array [ "zero", "one", "two", <1 个空的存储位置> ]</script>
Array
这是我们想要的基对象名称
prototype
Array.prototype.slice.call == [].slice.call
object
であるかどうかを判断するための underscore.js
のソース コードです。 。 typeof
は次の 6 つの値を返すことがわかっています: object1 = { name:'frank', greet:function(){ alert('hello '+this.name) } }; object2 = { name:'trigkit4'};// object2没有greet方法// 但我们可以从object1中借来 object1.greet.call(object2);//弹出hello trigkit4🎜、
&&
は ||
よりも優先されます。 !!
は Boolean()
と同等であり、ブール値に変換されます。 🎜var t = function(){ console.log(this);// String [ "t", "r", "i", "g", "k", "i", "t", "4" ] console.log(typeof this); // Object console.log(this instanceof String); // true}; t.call('trigkit4');🎜同様に、
!!
は Boolean()
、nodeType の役割と同等です。 === 1
は要素ノードであることを意味し、属性 attr
は 2、テキスト text
は 3🎜1.toString ( ) 2.toLocaleString ( ) 3.valueOf ( ) 4.hasOwnProperty (V) 5.isPrototypeOf (V) 6.propertyIsEnumerable (V)🎜
firstChild code>attribute🎜<pre class="hljs javascript">jQuery.fn.extend({
on: function( types, selector, data, fn, /*INTERNAL*/ one ) { var type, origFn; // Types can be a map of types/handlers
if ( typeof types === "object" ) { // ( types-Object, selector, data )
if ( typeof selector !== "string" ) { // ( types-Object, data )
data = data || selector;
selector = undefined;
}
}
})
jQuery.extend(object) :为扩展jQuery类本身.为类添加新的方法。
jQuery.fn.extend(object) :给jQuery对象添加方法。</pre>🎜text ノードもノードとみなされ、pの子ノードはテキストノードなので3を返す🎜🎜zeptoソースコード🎜<h3>配列かどうか判断</h3><pre class="hljs javascript">type: function( obj ) { if ( obj == null ) { return obj + "";
} return typeof obj === "object" || typeof obj === "function" ?
class2type[ toString.call(obj) ] || "object" : typeof obj;
},</pre>🎜 <code>Array.isArray()
メソッド: オブジェクトが配列の場合は true
を返し、そうでない場合は false
を返します。 🎜🎜instanceof
は、🎜rrreee🎜 など、変数がオブジェクトのインスタンスであるかどうかを判断するために使用されます。同時に、alert(a instanceof Object)
も返されます。 true
🎜🎜isArray
はブール値を返します。Array.isArray
が true
の場合は、true を返します。
、それ以外の場合は、配列のオブジェクトインスタンスを返します。 🎜class2type
は空のオブジェクトです 実際には、この Object.create(null); / のように何も入っていない空のオブジェクトが作成されます。 code>🎜🎜 データ型は、<code>Object.prototype.toString.call()
メソッドを通じて決定できます。例: 🎜rrreee🎜 まず、パラメータ obj
が unknown
または null
を選択し、対応する元の文字列 "unknown
" または " through <code>String(obj) null
"。 🎜🎜次に、class2type[toString.call(obj)]
は最初に Object
のプロトタイプ メソッド toString()
を借用して obj の文字列表現。戻り値は <code>[オブジェクト クラス]
の形式になります。class
は内部オブジェクト クラスです。 🎜🎜次に、オブジェクト class2type
から [object class]
に対応する小文字の文字列を取り出し、取得されない場合は常に "object
を返します。 > . 🎜idx
が 0 より小さい場合、idx
は次のようになります。 idx+length
と同じです。length
はコレクションの長さです 🎜🎜slice.call(this)
を見たときに混乱しているかもしれません。 > とありますが、実は zepto だけではありません <code>jQuery
を含む .js のソースコードと backbone
のソースコードがすべて書かれています🎜rrreee🎜Soslice.call(this) は実際には Array.slce.call(this)
です🎜🎜 プロトタイプです。 js ソース コード🎜rrreee🎜 なぜなら、addClassName
は removeClassName()
に依存しているため、最初に後者を分析してください。 $()
は要素を にカプセル化します。 prototype
オブジェクト。🎜rrreee🎜 の意味は、要素オブジェクトが存在しない場合、実行を続行しないという意味は無視され、🎜rrreee🎜 が空の文字列 () の場合は終了することを意味します。 "
) が区切り文字として使用されると、各文字が分割されます。 🎜!Array.prototype .push
true
の場合、ブラウザがこのメソッドをサポートしていないことを意味し、this[ startLength + i] = argument[i]
が渡されます。受け取った各パラメーターが順番に配列に入れられ、最後に配列の長さが返されます🎜🎜アクセス オブジェクトには、(.) 表記または []
と同じ方法で配列要素にアクセスします。 🎜🎜jQuery ソース コード 🎜🎜jQuery
ソース コードには接続が多すぎます。ので、個別に分析するのは簡単ではありません。簡単な例を 1 つまたは 2 つ挙げてみましょう。 🎜Array.prototype.slice.call(arguments)
は、 length
属性を持つオブジェクトを配列に変換します。つまり、その目的は arguments
オブジェクトの配列が抽出され、配列に変換されます。例: 🎜rrreee🎜Array
🎜これは、必要な基本オブジェクトの名前です🎜🎜prototype
🎜これは、配列🎜slice
这提取数组的一部分并返回新的数组,并没有开始和结束索引,它只是返回一个数组的拷贝
call
这是一个非常有用的功能,它允许你从一个对象调用一个函数并且使用它在另一个上下文环境
下面的写法是等效的:
Array.prototype.slice.call == [].slice.call
看这个例子:
object1 = { name:'frank', greet:function(){ alert('hello '+this.name) } }; object2 = { name:'trigkit4'};// object2没有greet方法// 但我们可以从object1中借来 object1.greet.call(object2);//弹出hello trigkit4
分解一下就是object1.greet
运行弹出hello + 'this.name'
,然后object2
对象冒充,this
就指代object2
var t = function(){ console.log(this);// String [ "t", "r", "i", "g", "k", "i", "t", "4" ] console.log(typeof this); // Object console.log(this instanceof String); // true}; t.call('trigkit4');
call(this)
指向了所传进去的对象。
在Object.prototype
中已经包含了一些方法:
1.toString ( ) 2.toLocaleString ( ) 3.valueOf ( ) 4.hasOwnProperty (V) 5.isPrototypeOf (V) 6.propertyIsEnumerable (V)
jQuery.fn.extend({ on: function( types, selector, data, fn, /*INTERNAL*/ one ) { var type, origFn; // Types can be a map of types/handlers if ( typeof types === "object" ) { // ( types-Object, selector, data ) if ( typeof selector !== "string" ) { // ( types-Object, data ) data = data || selector; selector = undefined; } } }) jQuery.extend(object) :为扩展jQuery类本身.为类添加新的方法。 jQuery.fn.extend(object) :给jQuery对象添加方法。
!=
在表达式两边的数据类型不一致时,会隐式转换为相同数据类型,然后对值进行比较.!==
不会进行类型转换,在比较时除了对值进行比较以外,还比较两边的数据类型, 它是恒等运算符===
的非形式。
on : function(){}
是js
对象字面量的写法
{键:值,键:值}
语法中的“健/值”
会成为对象的静态成员。如果给某个“健”指定的值是一个匿名函数,那么该函数就会变成对象的静态方法;否则就是对象的一个静态属性。
type: function( obj ) { if ( obj == null ) { return obj + ""; } return typeof obj === "object" || typeof obj === "function" ? class2type[ toString.call(obj) ] || "object" : typeof obj; },
前面已经分析了,class2type = {};
所以class2type[ toString.call(obj) ]
={}.toString.call(obj)
。它的作用是改变toString
的this
指向为object
的实例。
以上がjsフレームワークのソースコード調査の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。