您的位置:首页 > Web前端 > JQuery

jQuery的一些简单知识点(一)

2017-09-19 18:42 211 查看
1.必备tips1:Object.prototype.toString

/*
* Object.prototype.toString
* 作用:根据内部的this返回一个类似于这样的字符串'[object constructorName]'
* 这个方法有个缺点,不能获取用户自定义对象的具体类型,只能获取内置对象的类型。
* */

console.log(typeof []);//object
console.log([]);//根据打印找constructorName
console.log(Object.prototype.toString.call([]));//[object Array]

console.log(typeof new Date());//object
console.log(Object.prototype.toString.call(new Date()));//[object Date]

console.log(typeof Array);//function
console.log(Array); //ƒ Array() { [native code] }
console.log(Object.prototype.toString.call(Array));//[object Function]

console.log(typeof Date);//function
console.log(Object.prototype.toString.call(Date));//[object Function]

// 简写 ==> 因为{}对象直接继承Object.prototype,
// 所以通过这个对象得到的toString,一定来自Object.prototype。
//这里注意到{}外面加了一个小括号(),我们接下来会讲到,请往下看。
console.log(({}).toString.call([]));//[object Array]
console.log(({}).toString.call(new Date()));//[object Date]
console.log(({}).toString.call(Array));//[object Function]
console.log(({}).toString.call(Date));//[object Function]

// 用这个toString获取自定义对象的类型
//这个方法有个缺点,不能获取用户自定义对象的具体类型,只能获取内置对象的类型。
function Person() {}
var xiaofang = new Person();
console.log(({}).toString.call(xiaofang)); //[object Object]


2.必备tips2:{ }代码块 和 对象

/*
* 什么是代码块:
* 代码块就是一对大括号。
*
* 如果把一对大括号:
1.赋值给其他变量,例如:var myobj={},
2.或者参与运算,那么大括号就变成了字面对象,例如:用小括号包起来({})。
* */
var obj={};
console.log(obj);//看控制台打印,并展开观察原型中的方法,toString是其原型中的方法

{
var a = 1;
console.log(a);
}
console.log(typeof ({}));
console.log(typeof {});
// 需要通过运算,把{}转换为字面量,才能调用方法
console.log(({}).toString()); // '[object Object]'
console.log(obj.toString()); // '[object Object]'

// 错误,代码块不能调用方法
({}).toString();
// {}.toString(); 这样打开会报错


3.必备tips3:toString方法

<script>

// 字符串 ==> String.prototype.toString
var a="ddd";
console.log(a.toString());//ddd
var e= new String();
console.log(e.toString());//
var e= new String('string');
console.log(e.toString());//string

// 数组 ==> Array.prototype.toString
var b=[1,2,3,4,5,6];
console.log(b.toString());//1,2,3,4,5,6
var b=[];
console.log(b.toString());//
var d=new Array();
console.log(d.toString());//

// 对象  ==> Object.prototype.toString
var c={};
console.log(c.toString());//[object Object]

// 函数 ==> Function.prototype.toString
console.log(Function.toString());//function Function() { [native code] }
console.log(Array.toString());//function Array() { [native code] }
console.log(RegExp.toString());//function RegExp() { [native code] }
function fn() {
console.log('我写的');
}
console.log(fn.toString());
// function fn() {
//     console.log('我写的');
// }
</script>


4.jQuery的本质

<body>
<script>
// 真数组
var arr = [1, 2, 3];
console.log(arr);
console.log(({}).toString.call(arr));//[object Array]
console.log(arr.__proto__.constructor);//真数组的构造函数为"ƒ Array() { [native code] }函数"

/*
* jquery对外暴露了两个方法:jQuery和$,
* 这两方法实际上是同一个方法,
* 通过调用这两个方法,可以得到一个jQuery实例对象。
*
* jQuery实例对象是一个伪数组对象。
*
* jQuery和$实际上是一个工厂函数。
* */

// 工厂函数直接调用,就可以得到一个实例

var $div = $('<div></div>');
var jQueryDiv = jQuery('<div></div>');

console.log($div);
console.log($div.__proto__.constructor);//伪数组的构造函数不是"ƒ Array() { [native code] }函数"

console.log(jQueryDiv);
console.log(jQueryDiv.__proto__.constructor);

// 验证实例是伪装组
console.log(({}).toString.call($div));//[object Object]
</script>


4.真数组伪数组PK

<script>
/*
* 数组的分类:
*
* 1、真数组
* new Array 创建的数组,或者字面量形式 [] 创建的数组,都是真数组。
* 1.1 稀疏数组
* 数组中,某些下标不存在,即为稀疏数组。
* 1.2 非稀疏数组
* 数组中没有缺失任何值。
*
* 2、伪数组
* 必须要有length属性,
* 要么length为0,要么有length - 1为下标的属性。
* */

/*
* 伪数组的特点:
* 1、必须要有length属性
* 2、如果length属性值为0,那么这个对象有没有元素无所谓
* 3、如果length属性值不为0,那么这个对象一定有 (length - 1) 为下标的属性值。
* */

// 是伪装组
var obj = { length: 0 };
var obj = { length: 4, 3: 'a' }; // 没有0,1,2可以认为0,1,2存的是undefined
var obj = { length: 2, 0: 'a', 1: 'b' };

// 不是伪数组,因为没有 9(length - 1) 这个属性
var obj = { length: 10, 0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f' };
</script>


5.jQuery插件机制

<script>
/*
* jQuery插件实现机制:
* 就是给原型添加一些功能方法。
* */

// 咱们的自调结构,沿用了1.7的版本
(function( w ) {

// 对外暴露的工厂函数
function jQuery() {
return new jQuery.fn.init();
}

// 给原型提供一个简写方式
jQuery.fn = jQuery.prototype = {

};

// init是jQuery中真正的构造函数
var init = jQuery.fn.init = function() {

};

// 替换构造函数的原型 为 jQuery工厂的原型
//为了实现插件机制,让外界可以透过jQuery.fn扩充方法。
init.prototype = jQuery.fn;

// 把工厂通过两个变量暴露出去
w.jQuery = w.$ = jQuery;

}( window ));

// 实现一个jQ弹出框插件
jQuery.fn.alert = function( msg ) {
alert( msg );
};

// 测试插件
var $$ = $();
$$.alert('弹出框插件');
</script>


6.jQuery入口函数的实现思路

<script>

/*
* jQ入口函数根据不同参数创建实例的样式,入口函数的参数无非以下几种:
*
* 测试用例:
* 1、传入null、undefined、0、NaN、''
* 2、选择器
* 3、html片段
* 4、数组
* 5、伪数组
* 6、对象
* 7、其他基本数据类型
* 8、DOM
* */

简化版:
function init(selector){
if (!selector) {
//1、传入null、undefined、0、NaN、''返回空对象( 即空实例 )
return this;
}else if(typeof selector == 'string'){
if () {
//2、传入字符串,那么需要判断是HTML片段,如果是片段,则创建对应的DOM,然后添加到实例身上  $('<span>hello world</span>')
}else{
//否则按照选择器获取页面中的DOM,然后把获取到的DOM添加到实例身上。
//DOM元素 $('.test') $('#test') $('div')
}

}else if (){
//3、如果是数组或伪数组,那么把每一项分别添加到实例身上。
}else{
//4、除了上面的数据类型,剩余的,统一添加到实例身上。
}
}

细化版(简化版的细化版):
function init( selector ) {

// 传入null、undefined、0、NaN、''返回空对象( 即空实例 )
if ( !selector ) {
return this;
}

// 传入字符串,那么需要判断是html片段 还是 其它
else if ( typeof selector == 'string' ) {

// 如果是片段,则创建对应的DOM,然后添加到实例身上,
// 如果字符串的第一个字母是<,最后一个字母是>,并且length >= 3,就可以认为是html片段。
if (  ) {

/*
* 创建的思路:
* 1、先创建一个临时的div容器
* 2、设置这个div的innerHTML为html片段,
* 这些片段就自动转变为了div的子元素,
* 3、然后遍历div的子元素分别添加this身上,记住给实例补充length属性值,
*  可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。
* */

}

// 否则按照选择器获取页面中的DOM,然后把获取到的DOM添加到实例身上
else {

/*
* 实现的思路:
* 1、使用querySelectorAll获取页面中的元素
* 2、然后遍历获取到所有元素分别添加this身上,记住给实例补充length属性值,
* 可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。
* */
}

}

/*
* 判断是不是真假数组的思路:
* 1、先把函数和window排除掉,
* 2、然后通过toString来判断是不是真数组
* 3、否则再判断是不是伪数组
* 备注:下面的判断只用来判断是不是伪数组,不要用下面的判断条件判断真数组,
*       例如:[ 0:1, , , ] 使用下面的判断,就会得到false,造成真数组的误判。
* 3.1、 先看看这个对象有没有length属性,
* 3.2、 如果有,看看length的值是不是为0,如果为0,OK是伪数组,
* 3.3、 如果length的值不为0,看看这个数据有没有 length - 1这个属性,如果有,OK是伪数组。
* 建议把这个是否是真假数组的判断封装为一个函数,在这里调用。
* */
else if (  ) {

/*
* 实现的思路:
* 把真或伪数组中的每一项分别添加到实例身上,记住给实例补充length属性值,
* 可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。
* */
}
else {
/*
* 实现的思路:
* 把这个参数直接添加到实例身子,length为1即可。
* */
}

}
console.log(new init(null));;
</script>


7.细化版本中对字符串的处理

function init(selector){
if (!selector) {
//1、传入null、undefined、0、NaN、''返回空对象( 即空实例 )
return this;
}else if(typeof selector == 'string'){
if () {
//2、传入字符串,那么需要判断是HTML片段,如果是片段,则创建对应的DOM,然后添加到实例身上  $('<span>hello world</span>')
}else{
//否则按照选择器获取页面中的DOM,然后把获取到的DOM添加到实例身上。
//DOM元素 $('.test') $('#test') $('div')
}

}else if (){
//3、如果是数组或伪数组,那么把每一项分别添加到实例身上。
}else{
//4、除了上面的数据类型,剩余的,统一添加到实例身上。
}
}

// 判断是不是html片段
init.isHTML = function(html) {

// 如果是空类型的,直接返回false
if (!html) {
return false;
}

// 如果字符串的第一个字母是<,最后一个字母是>,并且length >= 3,就可以认为是html片段。
if (html.charAt(0) == '<' && html.charAt(html.length - 1) == '>' && html.length >= 3) {
return true;
}

return false;
}

// 去掉字符串首尾空白字符
init.trim = function(str) {

// 不是字符串就不处理了
if (typeof str !== 'string') {
return str;
}

// 优先使用内置的trim方法
if (str.trim) {
return str.trim();
}

// 把首尾空白字符替换为空,然后返回
return str.replace(/^\s+|\s+$/g, '');
}

function init(selector) {

// 传入null、undefined、0、NaN、''返回空对象( 即空实例 )
if (!selector) {
return this;
}

// 传入字符串,那么需要判断是html片段 还是 其它
else if (typeof selector == 'string') {

// 为了用户友好体验,先去掉首尾空白字符
selector = init.trim(selector);

// 如果是片段,则创建对应的DOM,然后添加到实例身上,
// 如果字符串的第一个字母是<,最后一个字母是>,并且length >= 3,就可以认为是html片段。
if (init.isHTML(selector)) {

/*
* 创建的思路:
* 1、先创建一个临时的div容器
* 2、设置这个div的innerHTML为html片段,
* 这些片段就自动转变为了div的子元素,
* 3、然后遍历div的子元素分别添加this身上,记住给实例补充length属性值,
*  可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。
* */
var tempDiv = document.createElement('div');
tempDiv.innerHTML = selector;
[].push.apply(this, tempDiv.childNodes);
return this;
}
// 否则按照选择器获取页面中的DOM,然后把获取到的DOM添加到实例身上
else {

/*
* 实现的思路:
* 1、使用querySelectorAll获取页面中的元素
* 2、然后遍历获取到所有元素分别添加this身上,记住给实例补充length属性值,
* 可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。
* */
try {
var nodes = document.querySelectorAll(selector);
[].push.apply(this, nodes);
return this;
} catch (e) {
this.length = 0;
return this;
}
}
}

/*
* 判断是不是真假数组的思路:
* 1、先把函数和window排除掉,
* 2、然后通过toString来判断是不是真数组
* 3、否则再判断是不是伪数组
* 备注:下面的判断只用来判断是不是伪数组,不要用下面的判断条件判断真数组,
*       例如:[ 0:1, , , ] 使用下面的判断,就会得到false,造成真数组的误判。
* 3.1、 先看看这个对象有没有length属性,
* 3.2、 如果有,看看length的值是不是为0,如果为0,OK是伪数组,
* 3.3、 如果length的值不为0,看看这个数据有没有 length - 1这个属性,如果有,OK是伪数组。
* 建议把这个是否是真假数组的判断封装为一个函数,在这里调用。
* */
else if (true) {

/*
* 实现的思路:
* 把真或伪数组中的每一项分别添加到实例身上,记住给实例补充length属性值,
* 可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。
* */
} else {
/*
* 实现的思路:
* 把这个参数直接添加到实例身子,length为1即可。
* */
}

}

// 测试html片段
var $spans = new init('<span>123</span>放松地放量加速离开的<span>321</span>');
console.log($spans);
var $divs = new init('<div><span>sdsfsdfs</span><span>dgdfgdf</span></div>');
document.body.appendChild($spans[0]);
document.body.appendChild($divs[0]);


8.入口函数对各种类型的判断原理

// 判断是不是html片段
init.isHTML = function(html) {

// 如果是空类型的,直接返回false
if (!html) {
return false;
}

// 如果字符串的第一个字母是<,最后一个字母是>,并且length >= 3,就可以认为是html片段。
if (html.charAt(0) == '<' && html.charAt(html.length - 1) == '>' && html.length >= 3) {
return true;
}

return false;
};

// 去掉字符串首尾空白字符
init.trim = function(str) {
// 不是字符串就不处理了
if (typeof str !== 'string') {
return str;
}
// 优先使用内置的trim方法
if (str.trim) {
return str.trim();
}
// 把首尾空白字符替换为空,然后返回
return str.replace(/^\s+|\s+$/g, '');
};

// 判断是不是函数
init.isFunction = function(fn) {
if (typeof fn == 'function') {
return true;
}
return false;
},
// 判断是不是window
init.isWindow = function(w) {
if (w.window == w) {
return true;
}
return false;
},

init.isLikeArray = function (arr){
if (init.isFunction(arr) || init.isWindow(arr) ||typeof arr!=='object') {
return false;
}
if (({}).toString.call(arr) == '[object Array]') {
return true;
}
}

// 判断是不是伪数组或真数组
init.isLikeArray = function(arr) {

// 过滤函数和window,以及非对象的其他数据

// 真数组(以下屏蔽的六行代码为)
// var arr=[];
// console.log(typeof arr);//object

// // 伪数组
// var obj ={length:0};
// console.log(typeof obj);//object

// console.log(({}).toString.call(arr));//[object Array]
// console.log(({}).toString.call(obj));//[object Object]

if (init.isFunction(arr) || init.isWindow(arr) || typeof arr !== 'object') {
return false;
}

// 判断是不是真数组
if (({}).toString.call(arr) == '[object Array]') {
return true;
}

// 判断是不是伪数组
// arr必须有length,在这个基础上,要么length为0,要么有length - 1这个属性值
if (('length' in arr) && ((arr.length === 0) || (arr.length - 1 in arr))) {
return true;
}
return false;
};

function init(selector) {

// 传入null、undefined、0、NaN、''返回空对象( 即空实例 )
if (!selector) {
return this;
}

// 传入字符串,那么需要判断是html片段 还是 其它
else if (typeof selector == 'string') {

// 为了用户友好体验,先去掉首尾空白字符
selector = init.trim(selector);

// 如果是片段,则创建对应的DOM,然后添加到实例身上,
// 如果字符串的第一个字母是<,最后一个字母是>,并且length >= 3,就可以认为是html片段。
if (init.isHTML(selector)) {

/*
* 创建的思路:
* 1、先创建一个临时的div容器
* 2、设置这个div的innerHTML为html片段,
* 这些片段就自动转变为了div的子元素,
* 3、然后遍历div的子元素分别添加this身上,记住给实例补充length属性值,
*  可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。
* */
var tempDiv = document.createElement('div');
tempDiv.innerHTML = selector;
[].push.apply(this, tempDiv.childNodes);
return this;
}

// 否则按照选择器获取页面中的DOM,然后把获取到的DOM添加到实例身上
else {

/*
* 实现的思路:
* 1、使用querySelectorAll获取页面中的元素
* 2、然后遍历获取到所有元素分别添加this身上,记住给实例补充length属性值,
* 可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。
* */
try {
var nodes = document.querySelectorAll(selector);
[].push.apply(this, nodes);
return this;
} catch (e) {
this.length = 0;
return this;
}
}

}

/*
* 判断是不是真假数组的思路:
* 1、先把函数和window排除掉,
* 2、然后通过toString来判断是不是真数组
* 3、否则再判断是不是伪数组
* 备注:下面的判断只用来判断是不是伪数组,不要用下面的判断条件判断真数组,
*       例如:[ 0:1, , , ] 使用下面的判断,就会得到false,造成真数组的误判。
* 3.1、 先看看这个对象有没有length属性,
* 3.2、 如果有,看看length的值是不是为0,如果为0,OK是伪数组,
* 3.3、 如果length的值不为0,看看这个数据有没有 length - 1这个属性,如果有,OK是伪数组。
* 建议把这个是否是真假数组的判断封装为一个函数,在这里调用。
* */
else if (init.isLikeArray(selector)) {

/*
* 实现的思路:
* 把真或伪数组中的每一项分别添加到实例身上,记住给实例补充length属性值,
* 可以使用数组的push来给实例添加,同时可以使用apply简化遍历过程。
* */
[].push.apply(this, selector);
} else {
/*
* 实现的思路:
* 把这个参数直接添加到实例身子,length为1即可。
* */
this[0] = selector;
this.length = 1;
}

}

// 测试html片段
/*var $spans = new init('<span>123</span>放松地放量加速离开的<span>321</span>');
console.log( $spans );
var $divs = new init('<div><span>sdsfsdfs</span><span>dgdfgdf</span></div>');
document.body.appendChild( $spans[0] );
document.body.appendChild( $divs[0] );*/

var a = new init([1, 2, 3, 4]);
console.log(a);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: