由Jquery建立对象激发的思索

读到jquery源码时我有以下迷惑

题目1 Jquery 中建立对象的奥妙
题目2 JavaScriptthis的指向题目
题目3 return this 的作用
题目4 instanceof / 对象和类之间的关联

//代码1(Jquery 建立对象)

var iQuery=function (){
    name="iQuery";   //4
    return new iQuery.prototype.init();   //1
};
iQuery.prototype={
    init : function(){
        name="iQueryPrototypeInit";   //5
        return this;   //2
    },

    name : "iQueryPrototype"   //6
};

iQuery.prototype.init.prototype=iQuery.prototype;   //3

这时候我有题目了,//1 处有没有new的区分。//2 处有没有 return this 的区分。 //3处的作用
在这里我经由过程对//代码1 举行剖析来回复 题目1 到 题目4

//代码2 我将 //代码1 中的 //3 处去掉 //2 处去掉 //1 处去掉

var iQuery=function (){
    name="iQuery";
    return iQuery.prototype.init();
};
iQuery.prototype={
    init : function(){
        name="iQueryPrototypeInit";   //5
    },

    name : "iQueryPrototype"
};

iQuery().name; //效果为  VM105:1 Uncaught TypeError: Cannot read property name of undefined(…)

剖析: iQuery.prototype.init() 是挪用了init函数,由于函数没有返回值,所以只返回了掌握 return iQuery.prototype.init() 也没有返回值iQuery().name;会有以上毛病提醒

//代码3

var iQuery=function (){
    name="iQuery";   //4
    return new iQuery.prototype.init();   //1
};
iQuery.prototype={
    init : function(){
        name="iQueryPrototypeInit";   //5
    },

    name : "iQueryPrototype"   //6
};

iQuery().name;  //效果为  undefined 这里并不提醒毛病,而是说name没有定义;

剖析: //4处 nameiQuery 的局部变量,//5 处nameinit的局部变量。
实行iQuery()时建立了一个init的对象,这时候init是组织函数,实行时流程

1 建立一个对象
2 返回新建的对象
这就是有没有 new 的区分

//代码4 多了个this

    var iQuery=function (){
        name="iQuery";   //4
        return new iQuery.prototype.init();   //1
    };
    iQuery.prototype={
        init : function(){
            this.name="iQueryPrototypeInit";   //5
        },
    
        name : "iQueryPrototype"   //6
    };

iQuery().name;  //效果为  `iQueryPrototypeInit`

剖析: 实行 iQuery().name;实行流程

1 建立一个对象
2 让 this 援用这个对象
3 为 this 所援用的对象增加属性 name
4 返回 this 所援用的对象

iQuery() instanceof iQuery  //false
iQuery() instanceof iQuery.prototype  //VM125:1 Uncaught TypeError: Right-hand side of 'instanceof' is not callable(…)

iQuery.prototype 是一个对象 instanceof 右侧必需是类,即函数名

iQuery() instanceof iQuery.prototype.init;  //true

这里挪用 iQuery() 是建立了init的一个对象。

//代码5 多了//2

var iQuery=function (){
    name="iQuery";   //4
    return new iQuery.prototype.init();   //1
};
iQuery.prototype={
    init : function(){
        this.name="iQueryPrototypeInit";   //5
        return this;   //2
    },

    name : "iQueryPrototype"   //6
};

iQuery().name;  //效果为  iQueryPrototypeInit

剖析: 实行 iQuery().name;实行流程

1 建立一个对象
2 让 this 援用这个对象
3 为 this 所援用的对象增加属性 name
4 返回 this 所援用的对象

iQuery() instanceof iQuery  //false
iQuery() instanceof iQuery.prototype  //VM125:1 Uncaught TypeError: Right-hand side of 'instanceof' is not callable(…)

iQuery.prototype 是一个对象 instanceof 右侧必需是类,即函数名

iQuery() instanceof iQuery.prototype.init;  //true

这里挪用 iQuery() 是建立了init的一个对象。

总结1 假如运用new建立对象加不加 return this 是一样的。

//代码6 去掉//1 处的 new //2处有 return this

var iQuery=function (){
    name="iQuery";   //4
    return iQuery.prototype.init();   //1
};
iQuery.prototype={
    init : function(){
        this.name="iQueryPrototypeInit";   //5
        return this;   //2
    },

    name : "iQueryPrototype"   //6
};
iQuery().name;   // iQueryPrototypeInit

假如去掉 //5

iQuery().name;   // iQueryPrototype

剖析: 实行 iQuery() 返回了 iQuery.prototype 这个由字面常量建立的对象

假如没有去掉 //5 则给 iQuery.prototype 增加了 name 属性覆蓋了原有的name
在这里 iQuery.prototype.init()iQuery.prototype 这个对象挪用了 init 函数
所以 initthis 指向了 iQuery.prototype

结论2: 函数中的 this 一直指向直接挪用它的对象 ,注重是直接,为何说是直接 请看 //代码6

//代码7

var iQuery=function (){
    name="iQuery";   //4
    return iQuery.prototype.init();   //1
};
iQuery.prototype={
    init : function(){
        return this;   //2
    },

    name : "iQueryPrototype"   //6
};

var temp ={};
temp.name="temp";
temp.sayName=iQuery().init;  // 等价于 temp.sayName=iQuery.prototype.init;
temp.name;   // 效果  temp
temp.sayName.name;   // 效果  temp

剖析: 实行 temp.sayName=iQuery().init; 为对象 temp 增加了一个 sayName 要领,sayName 援用了 iQuery().init/temp.sayName=iQuery.prototype.init这时候 init 中的 return this 这个 this 指向 temp 由于是 temp 直接挪用 init

总结:JavaScript中的 this 是上下文 这个上下文特指是函数的上下文,就是函数所属的对象JavaScript中的 bind,call,apply 要领都能切换 函数的上下文,这和代码 //6 的道理雷同都是转变 this 的指向,所以叫做上下文切换

//代码8 (本文最主要的点) 对象和类之间的关联(instanceof)

var iQuery=function (){
    name="iQuery";   //4
    return new iQuery.prototype.init();   //1
};
iQuery.prototype={
    init : function(){
    },

    name : "iQueryPrototype"   //6
};

iQuery.prototype.init.prototype=iQuery.prototype;   //3

// 注重 增加了 //3
这时候实行:

a: iQuery() instanceof iQuery().init; //true
b: iQuery() instanceof iQuery; //true;

假如去掉 //3
c: iQuery() instanceof iQuery; //false;

剖析: 我挪用 iQuery() 建立的明显是 组织器 init 的对象啊 a:的效果才是相符逻辑的效果,b: 是什么鬼啊,和他有毛关联啊

  请看  //代码9  //代码10

//代码9

var pro={};
var A=function(){};
A.prototype=pro;
var B=function(){};
B.prototype=pro;
var a=new A();
var b=new B();
实行:
a instanceof A;   //true
a instanceof B;   //true
b instanceof A;   //true
b instanceof B;   //true

//代码10

var pro={};
var A=function(){};
A.prototype=pro;
var B=function(){};
B.prototype=pro;
var a=new A();
var b=new B();
var C=function(){};
C.prototype=a;
var c=new C();

c instanceof A;   //true
c instanceof B;   //true
c instanceof C;   //true

剖析: 看到这里人人一定会邃晓Jquery的设计者为何加 iQuery.prototype.init.prototype=iQuery.prototype;

虽然源码中用了 fn 然则 fn 就是 Jquery.prototype我给出我的结论

结论3: JavaScript 中的对象和类(即 组织器) 之间除了 对象的_proto_ 属性指向了 类(组织器)指定的 prototype以外,对象和类之间没有更多的关联。范例完全由 prototype 决议。具有雷同 prototype 的一切组织器的对象都具有雷同的范例

末了: Jquery中的init中有 return this 关于运用 new 函数名() 如许的体式格局建立对象有没有 return this 是一样的。那Jquery为何加啊,由于Jquery中的许多别的要领能够举行链式挪用,这些要领中经由过程 return this 返回由init建立的对象,为了保持一致 所以init中的 return this 真的能够去掉。关于运用 new 函数名() 建立 对象 return this 和无返回值一样由于默许就会返回 thisreturn 基础范例,则 return 会被疏忽依旧 return this。 假如 return 援用范例 那末返回效果就是 援用范例的对象。

    原文作者:_ivenj
    原文地址: https://segmentfault.com/a/1190000006816162
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞