SOURCE

/*
1、如何实现jQuery(selector).do(). 

var jQuery = function(selector, context) {
  return new jQuery();
}
jQuery.prototype = {
  name: function() {},
  age: function() {}
}
这样的话,代码陷入死循环了!

*/
//每次执行函数都产生新的实例并直接应用,makeCar().getModel()
//不需要采用var car = new Car('Eagle', 'Talon TSi', 1993),car.name的方式
//函数运行后得到实例然后直接使用,这也是jquery的便利的起点。
function Car(make, model, year) {
  this.make = make;
  this.getModel = function() {return model};
  this.year = year;
}
 function makeCar(){
 return new Car('makeCar().make', 'makeCar().getModel()', 1993); 
 }
console.log(makeCar().make);
console.log(makeCar().getModel());
const car1 = new Car('car1.make', 'car1.getModel()', 1993);
console.log(car1.make);
console.log(car1.getModel());






/*
2、不用new情况下如何? 
    this指向调用它的对象。
    所以,下面this永远指向jQueryOne.prototype,
    也就是每次返回对象都是jQueryOne.prototype,而不是实例对象。

*/

var jQueryOne = function(selector, context) {
       return  jQueryOne.prototype.init();//不用new情况下
}
jQueryOne.prototype = {
    init: function() {
        this.name=function() {return "jQueryOne init"};
        //这里的 this 指向原型对象,所以会覆盖掉定义中的name: function() {return "jQueryOne"},
        console.log("this===jQueryOne.prototype: "+(this===jQueryOne.prototype));
        return this; 
        // 这里的 this 指向原型对象,所以执行jQueryOne.prototype.init()后,
        //实际上返回的是jQueryOne.prototype,也就不能构造不同的实例。
    },
    name: function() {return "jQueryOne"},
    age: function() {return 18}

}
console.log(jQueryOne().name());
console.log(jQueryOne().age());//init里面为定义age,但是this指向的是prototype,所以可以访问prototype的方法。
//> jQueryOne init
//> 18

console.log("==========="+(jQueryOne().name===jQueryOne.prototype.name))//true
console.log("==========="+(jQueryOne().name===jQueryOne().name))//false?????????为什么都是jQueryOne.prototype.name却不等?


/*
3、new情况下如何? 
     使用new,每次都生成新的实例,这里的 this 指向 new init 生成的对象,和prototype无关。

*/

var jQueryNew = function(selector, context) {
       return new jQueryNew.prototype.init();//使用new。
}
jQueryNew.prototype = {
    init: function() {
        this.name = function() {return "jQueryNew initName"};
        console.log("this===jQueryNew.prototype: "+(this===jQueryOne.prototype));
        return this; // 使用new,这里的 this 指向 new init 生成的对象,和prototype无关。
    },
    name: function() {return "jQueryNew"},
    age: function() {return 18}
}

console.log(jQueryNew().name());
//console.log(jQueryNew().age());
//> jQueryNew initName
//> Uncaught TypeError: jQueryNew(...).age is not a function
//jQueryNew().age()无法执行的原因:jQueryNew()是init的实例,实例代码中只有name方法,没有age方法。
//age方法属于jQueryNew.prototype ,和int实例无关。如何让init的实例可以访问jQueryNew.prototype的方法。

/*
4、实例访问原型方法: 
     使用new,每次都生成新的实例,这里的 this 指向 new init 生成的对象,和jQueryNewAndRnewPro.prototype无关。
     将jQueryNewAndRnewPro.prototype赋值给init.prototype后,init的实例就可以通过原型访问到jQueryNewAndRnewPro.prototype方法。
*/

var jQueryNewAndRnewPro = function(selector, context) {
       return new jQueryNewAndRnewPro.prototype.init();//使用new。
}
jQueryNewAndRnewPro.prototype = {
    init: function() {
        this.name = function() {return "jQueryNewAndRnewPro initName"};
        return this; // 使用new,这里的 this 指向 new init 生成的对象,和prototype无关。
    },
    name: function() {return "jQueryNewAndRnewPro"},
    age: function() {return 18}
}
jQueryNewAndRnewPro.prototype.init.prototype = jQueryNewAndRnewPro.prototype;
//将jQueryNewAndRnewPro.prototype.init.prototype 指向jQueryNewAndRnewPro.prototype后,就可以访问其原型方法
console.log(jQueryNewAndRnewPro().name());
console.log(jQueryNewAndRnewPro().age());
//> jQueryNewAndRnewPro initName
//> 18

//简化jquery代码
//init为什么放到原型上?不在原型上如何?
//任何jquery实例可以访问init,为什么?
(function () {
    "use strict";
    var version = "3.5.1",
        jQuery = function jQuery(selector, context) {
            return new jQuery.fn.init(selector, context);
        };
    jQuery.fn = jQuery.prototype = {
        constructor: jQuery,
        jquery: version,
        length: 0,
    };
    
    var init = jQuery.fn.init = function init(selector, context, root) {
        //...
        };
    init.prototype = jQuery.fn;
    //...
    window.jQuery = window.$ = jQuery;

    console.log(jQuery().init);
})();

//init不放到原型上
(function () {
    "use strict";
    var version = "3.5.1",
        jQuery = function jQuery(selector, context) {
            return new jQuery.init(selector, context);
        };
    jQuery.prototype = {
        constructor: jQuery,
        jquery: "1111",
        length: 0,
    };
    
    jQuery.init = function init(selector, context, root) {
       console.log("init begin");
        };
    jQuery.init.prototype = jQuery.prototype
    //...
   console.log(jQuery().jquery);
})();

//任意init
(function () {
    "use strict";
    var version = "3.5.1",
        jQuery = function jQuery(selector, context) {
            return new init(selector, context);
        };
    jQuery.prototype = {
        constructor: '',
        jquery: "1111",
        length: 0,
    };
    
    var init = function init(selector, context, root) {
       console.log("init begin");
        };
    init.prototype = jQuery.prototype
    //...
   console.log(jQuery().jquery);
})();


/*
执行 $([selector]) 方法,过程如下

相当于执行 new jQuery.fn.init(selector, context); ,返回的是 init  方法(类)的实例,假设这个实例是 A
那么: 可以得出 A.__proto__===init.prototype
又由代码可以得知 init.prototype  =>  jQuery.fn  =>  jQuery.prototype ,让 init 的原型重定向为jQuery的原型,所以最终执行 new init 相当于执行了 new jQuery
所以 A.__proto__===jQuery.prototype

总结:基于JQ选择器 $(...) 、 jQuery(...) 获取的是 jQuery 类的实例

目的:让用户使用的时候把 jQuery /  $ 当做普通函数执行,但是最后的结果是创造其类的一个实例,用户使用起来方便
这种处理模式的思想其实就是工厂设计模式

*/
console 命令行工具 X clear

                    
>
console