jsフレームワークのソースコード調査

巴扎黑
リリース: 2017-08-10 13:21:30
オリジナル
1473 人が閲覧しました

【はじめに】Underscore js のソースコード Underscore js はネイティブ JavaScript オブジェクトを拡張するのではなく、_() メソッドを呼び出してカプセル化します。カプセル化が完了すると、ネイティブ JavaScript オブジェクトは Underscore オブジェクトになります。指定された変数がオブジェクトであるかどうかを判断します

underscore.js のソース コード

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(),将其转换为布尔值。

判断给定值是否是DOM元素

// 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(&#39;test&#39;);
    alert(t.nodeType);//1
    alert(t.nodeName);//p
    alert(t.nodeValue);//null</script></body>
ログイン後にコピー

firstChild属性

var t = document.getElementById(&#39;test&#39;).firstChild;
alert(t.nodeType);//3alert(t.nodeName);//#testalert(t.nodeValue);//测试
ログイン後にコピー

文本节点也算是一个节点,所以p的子节点是文本节点,所以返回3

zepto源码

判断是否是数组

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.isArraytrue,则返回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(&#39;123&#39;)) //[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]
ログイン後にコピー

首先如果参数objundefinednull,则通过String(obj)转换为对应的原始字符串“undefined”或“null”。

然后class2type[toString.call(obj)]首先借用Object的原型方法toString()来获取obj的字符串表示,返回值的形式是 [object class],其中的class是内部对象类。

然后从对象class2type中取出[object class]对应的小写字符串并返回;如果未取到则一律返回“object

get方法

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的源码,包括jQuerybackbone的源码都是这么写的,只不过它们在最开头做了声明:

var push = array.push;var slice = array.slice;var splice = array.splice;
ログイン後にコピー

所以slice.call(this)其实还是Array.slce.call(this)

prototype.js源码

  //为对象添加 class 属性值

   addClassName: function(element, className) {
        element = $(element);
        Element.removeClassName(element, className);
        element.className += &#39; &#39; + className;
    },   //为对象移除 class 属性值

    removeClassName: function(element, className) {
        element = $(element);        if (!element)            return;        var newClassName = &#39;&#39;;        var a = element.className.split(&#39; &#39;);        for (var i = 0; i < a.length; i++) {            if (a[i] != className) {                if (i > 0)
                    newClassName += &#39; &#39;;
                newClassName += a[i];
            }
        }
        element.className = newClassName;
    },
ログイン後にコピー

因为addClassName依赖于removeClassName(),所以先分析后者,$()是先将元素封装成prototype对象,

if(!element)  return
ログイン後にコピー

这句的意思就是如果元素对象不存在,则忽略不再继续执行的意思,也就是终止的意思。

split() 方法用于把一个字符串分割成字符串数组。
ログイン後にコピー

如果把空字符串 ("") 用作 分隔符,那么 该对象 中的每个字符之间都会被分割。

判断是否拥有 class 属性值

//是否拥有 class 属性值hasClassName: function(element, className) {
    element = $(element);    if (!element)        return;    var a = element.className.split(&#39; &#39;);    for (var i = 0; i < a.length; i++) {        if (a[i] == className)            return true;//返回正确的处理结果
    }    return false;//返回错误的处理结果},
ログイン後にコピー

兼容旧版本浏览器增加Array的push方法

/**
 * 为兼容旧版本的浏览器增加 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源码太多关联了,所以不好单独拿出来做分析,就举一两个简单的例子吧:

toArray方法

jQuery.prototype = {
    toArray: function() {            return slice.call( this );
        },
}
ログイン後にコピー

Array.prototype.slice.call(arguments)能将具有length属性的对象转成数组,也就是说其目的是将arguments对象的数组提出来转化为数组。例如:

<script>
    var a = {length:4,0:&#39;zero&#39;,1:&#39;one&#39;,2:&#39;two&#39;};    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:&#39;frank&#39;,
    greet:function(){
        alert(&#39;hello &#39;+this.name)
    }
};

object2 = {
    name:&#39;trigkit4&#39;};// object2没有greet方法// 但我们可以从object1中借来

 object1.greet.call(object2);//弹出hello trigkit4
ログイン後にコピー
ログイン後にコピー
🎜、&&|| よりも優先されます。 !!Boolean() と同等であり、ブール値に変換されます。 🎜

指定された値が DOM 要素であるかどうかを判断する

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(&#39;trigkit4&#39;);
ログイン後にコピー
ログイン後にコピー
🎜同様に、!!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🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><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 === &quot;object&quot; ) { // ( types-Object, selector, data ) if ( typeof selector !== &quot;string&quot; ) { // ( types-Object, data ) data = data || selector; selector = undefined; } } }) jQuery.extend(object) :为扩展jQuery类本身.为类添加新的方法。 jQuery.fn.extend(object) :给jQuery对象添加方法。</pre><div class="contentsignin">ログイン後にコピー</div></div><div class="contentsignin">ログイン後にコピー</div></div>🎜text ノードもノードとみなされ、pの子ノードはテキストノードなので3を返す🎜🎜zeptoソースコード🎜<h3>配列かどうか判断</h3><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="hljs javascript">type: function( obj ) { if ( obj == null ) { return obj + &quot;&quot;; } return typeof obj === &quot;object&quot; || typeof obj === &quot;function&quot; ? class2type[ toString.call(obj) ] || &quot;object&quot; : typeof obj; },</pre><div class="contentsignin">ログイン後にコピー</div></div><div class="contentsignin">ログイン後にコピー</div></div>🎜 <code>Array.isArray() メソッド: オブジェクトが配列の場合は true を返し、そうでない場合は false を返します。 🎜🎜instanceof は、🎜rrreee🎜 など、変数がオブジェクトのインスタンスであるかどうかを判断するために使用されます。同時に、alert(a instanceof Object) も返されます。 true</code >🎜🎜<code>isArray はブール値を返します。Array.isArraytrue の場合は、true を返します。 、それ以外の場合は、< コードの結果>配列のオブジェクトインスタンスを返します。 🎜

データ型判定

rrreee🎜class2type は空のオブジェクトです 実際には、この Object.create(null);</ / のように何も入っていない空のオブジェクトが作成されます。 code>🎜🎜 データ型は、<code>Object.prototype.toString.call() メソッドを通じて決定できます。例: 🎜rrreee🎜 まず、パラメータ obj unknown または null を選択し、対応する元の文字列 "unknown" または " through <code>String(obj)<" に変換します。 /code> null"。 🎜🎜次に、class2type[toString.call(obj)] は最初に Object のプロトタイプ メソッド toString() を借用して obj< を取得します。 /code code> の文字列表現。戻り値は <code>[オブジェクト クラス] の形式になります。class は内部オブジェクト クラスです。 🎜🎜次に、オブジェクト class2type から [object class] に対応する小文字の文字列を取り出し、取得されない場合は常に "object を返します。 > . 🎜

get メソッド

rrreee🎜 idx が 0 より小さい場合、idx は次のようになります。 idx+length と同じです。length はコレクションの長さです 🎜🎜slice.call(this) を見たときに混乱しているかもしれません。 > とありますが、実は zepto だけではありません <code>jQuery を含む .js のソースコードと backbone のソースコードがすべて書かれています🎜rrreee🎜So< code>slice.call(this) は実際には Array.slce.call(this) です🎜🎜 プロトタイプです。 js ソース コード🎜rrreee🎜 なぜなら、addClassNameremoveClassName() に依存しているため、最初に後者を分析してください。 $() は要素を にカプセル化します。 prototype オブジェクト。🎜rrreee🎜 の意味は、要素オブジェクトが存在しない場合、実行を続行しないという意味は無視され、🎜rrreee🎜 が空の文字列 () の場合は終了することを意味します。 ") が区切り文字として使用されると、各文字が分割されます。 🎜

クラス属性値があるかどうかを確認します

rrreee

配列プッシュを追加するための古いバージョンのブラウザーとの互換性method

rrreee🎜!Array.prototype .pushtrue の場合、ブラウザがこのメソッドをサポートしていないことを意味し、this[ startLength + i] = argument[i] が渡されます。受け取った各パラメーターが順番に配列に入れられ、最後に配列の長さが返されます🎜🎜アクセス オブジェクトには、< を使用してアクセスできます。 code>(.) 表記または [] と同じ方法で配列要素にアクセスします。 🎜🎜jQuery ソース コード 🎜🎜jQuery ソース コードには接続が多すぎます。ので、個別に分析するのは簡単ではありません。簡単な例を 1 つまたは 2 つ挙げてみましょう。 🎜

toArray メソッド

rrreee🎜Array.prototype.slice.call(arguments) は、 length 属性を持つオブジェクトを配列に変換します。つまり、その目的は arguments オブジェクトの配列が抽出され、配列に変換されます。例: 🎜rrreee🎜Array🎜これは、必要な基本オブジェクトの名前です🎜🎜prototype🎜これは、配列🎜

slice
这提取数组的一部分并返回新的数组,并没有开始和结束索引,它只是返回一个数组的拷贝

call
这是一个非常有用的功能,它允许你从一个对象调用一个函数并且使用它在另一个上下文环境

下面的写法是等效的:

Array.prototype.slice.call == [].slice.call
ログイン後にコピー
ログイン後にコピー

看这个例子:

object1 = {
    name:&#39;frank&#39;,
    greet:function(){
        alert(&#39;hello &#39;+this.name)
    }
};

object2 = {
    name:&#39;trigkit4&#39;};// object2没有greet方法// 但我们可以从object1中借来

 object1.greet.call(object2);//弹出hello trigkit4
ログイン後にコピー
ログイン後にコピー

分解一下就是object1.greet运行弹出hello + &#39;this.name&#39;,然后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(&#39;trigkit4&#39;);
ログイン後にコピー
ログイン後にコピー

call(this)指向了所传进去的对象。

Object.prototype中已经包含了一些方法:

    1.toString ( )

    2.toLocaleString ( )

    3.valueOf ( )

    4.hasOwnProperty (V)

    5.isPrototypeOf (V)

    6.propertyIsEnumerable (V)
ログイン後にコピー
ログイン後にコピー

on方法

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对象字面量的写法

{键:值,键:值}语法中的“健/值”会成为对象的静态成员。如果给某个“健”指定的值是一个匿名函数,那么该函数就会变成对象的静态方法;否则就是对象的一个静态属性。
jsフレームワークのソースコード調査

jQuery类型判断

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)。它的作用是改变toStringthis指向为object的实例。

以上がjsフレームワークのソースコード調査の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート