如果不使用new,aQuery()得到的永远是一个对象aQuery.prototype,因为aQuery.prototype调用init()函数,this就指向aQuery.prototype,aQuery()运行的值永远是一个结果,这样是不可以的,所以要使用new
var aQuery = function(selector, context) {
return aQuery.prototype.init();
}
aQuery.prototype = {
init:function(){
return this;
},
name:function(){},
age:function(){}
}
var aa = aQuery();
var bb = aQuery();
console.log(aa === aQuery.prototype);//true
console.log(aa === bb);//true
如果使用new,就可以改变this指向,
var obj;
function Test(){
this.name = 'Jack'
console.log(this);
console.log({}.toString.call(this) );
console.log(this.__proto__);
obj = this;
}
Test.prototype.a = 100;
//test();
var aa = new Test();
console.log(aa ===obj);//true
console.log(aa.__proto__ === Test.prototype);//true
只要使用了new,无论函数前面有没有调用对象,都相当于不存在,因为new会改变this指向,
new aQuery.prototype.init();相当于new init();aQuery.prototype只是提供了使用权限,否则无法访问init(),
但是又出现了另一个问题var obj = new aQuery.prototype.init();obj只能访问init.prototype对象下的属性和方法,
不能访问aQuery.prototype对象下的属性和方法,如果要访问aQuery.prototype对象下的属性和方法,只能
init.prototype = aQuery.prototype
var aQuery = function(selector, context) {
return new aQuery.prototype.init();
}
aQuery.prototype = {
init: function() {
this.age = 18
return this;
},
name: function() {},
age: 20
}
console.log(aQuery().name());// Uncaught TypeError: aQuery(...).name is not a function
将init.prototype = aQuery.prototype,
var aQuery = function(selector, context) {
return new aQuery.prototype.init();
}
aQuery.prototype = {
init: function() {
return this;
},
name: function() {
return this.age
},
age: 20
}
aQuery.prototype.init.prototype = aQuery.prototype;
console.log(aQuery().name()) //20
$()参数的使用:
$(),$(""), $(null), $(undefined), $(false)
//返回结果是空的jQuery对象,jQuery对象是类数组,空jQuery对象,就是指没有0,1,2属性,
//这些数字属性对应的值存放的是原生的元素节点
$('<li></li>',{title : 'hi',html : 'abcd',css : {background:'red'}}).appendTo( 'ul' );
//首先判断title、html、css是不是jQuery实例的方法
//实例方法的情况:this.html('abcd');this.css({background:'red'})
//不是实例方法:this.attr(title,'hi')
$(DOMElement)
//将元素节点添加到jQuery对象的0属性,this[0] = DOMElement,this指jQuery对象
$(function(){})
//等价于$(document).ready(function(){});
$( $('#div1') )
//等价于$('#div1')
$([div,div,div])
//参数时dom数组,数组元素是元素节点,相当于jQuery.merge(this,[div,div,div])
//$({0: div,1:div,2:div})
init: function( selector, context, rootjQuery ) {
var match, elem;
// HANDLE: $(""), $(null), $(undefined), $(false)
if ( !selector ) {
return this;
}
// Handle HTML strings
if ( typeof selector === "string" ) {
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [ null, selector, null ];//$('<li>'),$('<li>1</li><li>2</li>')
} else {//$('#div1') $('.box') $('div') $('#div div.box') $('<li>hello')
match = rquickExpr.exec( selector );
//match=null; $('.box') $('div') $('#div div.box')
//match=['#div',null,'div'] $('#div1')
//match=['<li>hello','<li>',null]
}
// Match html or make sure no context is specified for #id
if ( match && (match[1] || !context) ) {
//能进入该if语句的是$('<li>'),$('#div1')
// HANDLE: $(html) -> $(array)
if ( match[1] ) {
context = context instanceof jQuery ? context[0] : context;
// scripts is true for back-compat
jQuery.merge( this, jQuery.parseHTML(
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true
) );
// HANDLE: $(html, props)
if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
for ( match in context ) {
// Properties of context are called as methods if possible
if ( jQuery.isFunction( this[ match ] ) ) {
this[ match ]( context[ match ] );
// ...and otherwise set as attributes
} else {
this.attr( match, context[ match ] );
}
}
}
return this;
// HANDLE: $(#id)
} else {
elem = document.getElementById( match[2] );
// Check parentNode to catch when Blackberry 4.6 returns
// nodes that are no longer in the document #6963
if ( elem && elem.parentNode ) {
// Inject the element directly into the jQuery object
this.length = 1;
this[0] = elem;
}
this.context = document;
this.selector = selector;
return this;
}
// HANDLE: $(expr, $(...))
} else if ( !context || context.jquery ) {
return ( context || rootjQuery ).find( selector );
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
return this.constructor( context ).find( selector );
}
// HANDLE: $(DOMElement)
} else if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
// HANDLE: $(function)
// Shortcut for document ready
} else if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector );
}
if ( selector.selector !== undefined ) {
this.selector = selector.selector;
this.context = selector.context;
}
return jQuery.makeArray( selector, this );
//该语句调用jQuery.merge(tihs,selector)
},
jQuery对象是类数组,拥有length属性和介于0~length-1的数值属性。jQuery对象还有四个的属性。selector 属性是创建jQuery对象时的选择器字符串(如果有的话)。context 属性是上下文对象,是传递给 $() 方法的第二参数,如果没有传递的话,默认是Document对象。prevObject,存放之前的jQuery对象,如果没有,则存放的是$(document)。最后,所有jQuery对象都有一个名为jquery的属性(该属性在原型对象上),检测该属性是否存在可以简单快捷地将jQuery对象与其他类数组对象区分开来。
<body>
<div>
<span> div中的span</span>
</div>
<span>独立的span</span>
<script type="text/javascript">
var obj = $('span').css({color:'red'});
console.log(obj);
</script>
</body>
<body>
<div>
<span> div中的span</span>
</div>
<span>独立的span</span>
<script type="text/javascript">
var obj = $('span',$("div").get(0)).css({color:'red'});
console.log(obj);
</script>
</body>
<body>
<div>
<span> div中的span</span>
</div>
<span>独立的span</span>
<script type="text/javascript">
var obj = $('span',$("div")).css({color:'red'});
console.log(obj);
</script>
</body>
当第二个参数是jQuery对象时,context属性还是document,但是selector不再是span而是div span。