你值得了解的JavaScript“继承之jquery”使用方法(代码详解)
之前的文章《深入解析JS中数组reduce方法(附代码)》中,给大家了解一下JS中数组reduce方法。下面本篇文章给大家了解一下JS-继承之jquery使用方法,小伙伴们可以参考一下。
jquery
截止到当前已经 3.3.1 版本了,如今随着各种浏览器的盛行,前端的框架层出不穷,jquery
独步天下,老夫写代码只用jquery
,拿起代码就是干的辉煌时代已经过去了。
2006 年,jQuery
的第一个版本的面世,凭借着简洁、灵活的编程风格受到了开发者的喜爱。而它本身是一个JavaScript
框架,它的设计的宗旨是“wrITe Less
,Do More
”,即倡导写更少的代码,做更多的事情。它封装了JavaScript
常用的功能代码,提供一种简便的JavaScript
设计模式,优化HTML
文档操作、事件处理、动画设计和Ajax
交互。
从之前的风靡到如今的被抛弃,究其原因,不少前端工程师表示,对于jQuery
来说,大量的操作DOM
虽然方便,但是会牺牲很多页面的性能。另一方面,现阶段React
、Vue
和Angularjs
等主流前端框架并不依赖jQuery
,都可以独立使用。况且浏览器的兼容问题越来越少,当浏览器兼容不再是问题时,jQuery的价值就大打折扣了
就在微软收购github
的 52 天,github
改变也已经放弃了jquery
,奇替代方案使用了原生的 js
:
使用
querySelectorAll
来查询DOM
节点;使用
fetch
来代替ajax
;事件处理使用了事件代理;
使用
DOM
标准化写了polyfill
;使用了自定义元素。
假如不用,学习下还是可以的
本文粗燥的实现jquery
的ready、each、bind、``$.fn.extend、$.extend
初始化$
(function (win) { VAR _$ = function (selector, context) { /** * 通常咱们定义一个 函数 var Fun = function(){ } * 然后定义一个 Fun.PRototyPE.init = function(){ } * 那么咱们调用init 的时候 得先要实例化对象 var f = new Fun() * 然后f.init() * 这里就省去了 var $ = new $() */ return new _$.prototype.Init(selector, context); } ; _$.prototype = { //初始化$ Init: function (selector, context) { this.elements = []; /** * 传入的类型是function 就执行ready事件,如果是document 就将document对象插入到this.elements * 主要就是判断$(document).ready 和 $(function(){ } ) 这两种的ready事件的写法 */ if (typeof selector === "function") { this.elements.push(document); this.ready(selector); } else { var context = context || document; var isDocument = (ele) => Object.prototype.toString.call(ele) == "[object HTMLDocument]" || "[object Document]"; if (isDocument(selector)) { this.elements.push(selector); } else { /** * 如果是字符串的话就查询该节点 $('.class') | $('#id') */ if (context.querySelectorAll) { var arr = context.querySelectorAll(selector); for (var i = 0; i arr.length; i++) { this.elements.push(arr[i]); } } } } } , //实现each each: function (callback) { } , //实现ready ready: function (callback) { } , //实现bind bind: function (type, callback) { } , } ; /** * 让两个作用域不一样的对象共享一个方法,让他们的原型指向一致,即Init.prototype = _$.prototype * 那么原型一致之后 就可以共享this.elements 属性了。 */ _$.prototype.Init.prototype = _$.prototype; window.$ = _$; } )(window || global);
ready
//实现readyready: function (callback) { var isDocument = (ele) => Object.prototype.toString.call(ele) == '[object HTMLDocument]' || '[object Document]' //如果已经取得了节点 if (isDocument(this.elements[0])) { if (document.addEventListener) { //判断火狐、谷歌 /** * DOM树构建完成的时候就会执行DOMContentLoaded * 页面上所有的DOM,样式表,脚本,图片,flash都已经加载完成了,才会触发window.onload * 这也就是$(document).ready() 比 window.onload 执行早的原因 * * arguments.callee 博客里面有一篇文章 [js-递归] 里面专门讲到了,这里不再解释了 */ document.addEventListener('DOMContentLoaded', function () { document.removeEventListener('DOMContentLoaded', arguments.callee, false) callback() } , false) } else if (document.attachEvent) { //判断IE document.attachEvent('onreadystatechange', function () { if (document.readyState == 'complete') { document.detachEvent('onreadystatechange', arguments.callee); callback() } } ) } else if (document.lastChild == document.body) { //body已经加载完了,就直接回调了 callback() } } } ,
each
//实现each each: function (callback) { if (this.elements.length > 0) { for (var i = 0; i this.elements.length; i++) { callback.call(this, this.elements[i], i); } } } ,
bind
//实现bindbind: function (type, callback) { if (document.addEventListener) { //判断火狐、谷歌 this.each(function (item, i) { item.addEventListener(type, callback, false) } ) } else if (document.attachEvent) { //判断IE this.each(function (item, i) { item.attachEvent('on' + type, callback) } ) } else { this.each(function (item, i) { //其他浏览器 egg: item.onclick = function(){ } item['on' + type] = callback } ) } }
$.fn.extend/$.extend
$.fn.extend
是为查询的节点对象扩展方法,是基于$
的原型扩展的方法
$.extend
是扩展常规方法,是$的静态方法
官方给出解释:
jQuery.extend()
: Merge the contents of two or more objects together into the First object.(把两个或者更多的对象合并到第一个当中)
jQuery.fn.extend()
:Merge the contents of an object onto the jQuery prototype to provide new jQuery instance methods.(把对象挂载到jQuery
的prototype
属性,来扩展一个新的jQuery
实例方法)
$.fn.extend
方法的初衷是我们扩展之后可以用$("").newMetod()
这样访问,实际上就是给$
原型加一个extend
方法。这中间的fn
其实类似于命名空间的作用,没什么实际的意义。为的是和$.extend
作区分
$.fn.extend
; (function (win) { ... _$.prototype.Init.prototype = _$.prototype; _$.fn = _$.prototype; //把对象挂载到jQuery的prototype属性 var isObj = (o) => Object.prototype.toString().call(o) === '[object Object]'; $.fn.extend = function (obj) { if (isObj(obj)) { for (var i in obj) { this[i] = obj //注意这里的this指向是 $.prototype } } }
$.extend
var isObj = (o) => Object.prototype.toString().call(o) === '[object Object]'; ..._$.extend = function (obj) { if (isObj(obj)) { for (var i in obj) { this[i] = obj[i]; //注意这里的this指向是 $ } } }
这俩看上去一模一样啊,没啥区别,注释里面已经说了,this
指向不同。咱们来看个例子:
!DOCTYPE html> html> head> title> jQuery.extend()与jQuery.fn.extend()区别/title> meta charset="utf-8" /> script type="text/javascript" src="jquery.js"> /script> !-- 开始扩展 --> script type="text/javascript"> (function ($) { $.extend({ sayHello: function () { console.LOG("Hello"); } , } ); $.fn.extend({ sayHello: function () { console.log("Hello"); } , } ); } )(jQuery); /script> !-- 调用 --> script type="text/javascript"> $(document).ready(function () { //$.extend扩展调用 $.sayHello(); //$.fn.extend扩展调用 $("#test").sayHello(); } ); /script> /head> body> div id="test"> /div> /body> /html>
这样以来就看的很明白了。jQuery.extend(object);
为扩展jQuery
类本身,为自身添加新的方法。$.xxx()
jQuery.fn.extend(object);
给jQuery
对象添加方法$('#test').xxx()
$.extend
常见用法
//在jquery全局对象中扩展一个net命名空间。$.extend({ net: { } } ); //方法扩展到之前扩展的Jquery的net命名空间中去。$.extend($.net, { sayHello: function () { console.log("Hello"); } ,} ); //extend方法还有一个重载原型//extend(boolean,dest,src1,src2,src3...),第一个参数boolean代表是否进行深度拷贝var a = { protocol: "http", hash: { a: 1, b: 2 } } ; var b = { host: "chuchur.COM", hash: { b: 1, c: 2 } } ; var result = $.extend(true, { } , a, b); console.log(result); //{ protocol: 'http',host: 'chuchur.com', hash: { a: 1, b: 1,c:2 } } var result = $.extend(false, { } , a, b); console.log(result); //{ protocol: 'http',host: 'chuchur.com', hash: { b: 1, c:2 } }
完整代码
(function (win) { var _$ = function (selector, context) { /** * 通常咱们定义一个 函数 var Fun = function(){ } * 然后定义一个 Fun.prototype.init = function(){ } * 那么咱们调用init 的时候 得先要实例化对象 var f = new Fun() * 然后f.init() * 这里就省去了 var $ = new $() */ return new _$.prototype.Init(selector, context); } ; _$.prototype = { //初始化$ Init: function (selector, context) { this.elements = []; /** * 传入的类型是function 就执行ready事件,如果是document 就将document对象插入到this.elements * 主要就是判断$(document).ready 和 $(function(){ } ) 这两种的ready事件的写法 */ if (typeof selector === "function") { this.elements.push(document); this.ready(selector); } else { var context = context || document; var isDocument = (ele) => Object.prototype.toString.call(ele) == "[object HTMLDocument]" || "[object Document]"; if (isDocument(selector)) { this.elements.push(selector); } else { /** * 如果是字符串的话就查询该节点 $('.class') | $('#id') */ if (context.querySelectorAll) { var arr = context.querySelectorAll(selector); for (var i = 0; i arr.length; i++) { this.elements.push(arr[i]); } } } } } , //实现each each: function (callback) { if (this.elements.length > 0) { for (var i = 0; i this.elements.length; i++) { callback.call(this, this.elements[i], i); } } } , //实现ready ready: function (callback) { var isDocument = (ele) => Object.prototype.toString.call(ele) == "[object HTMLDocument]" || "[object Document]"; //如果已经取得了节点 if (isDocument(this.elements[0])) { if (document.addEventListener) { //判断火狐、谷歌 /** * DOM树构建完成的时候就会执行DOMContentLoaded * 页面上所有的DOM,样式表,脚本,图片,flash都已经加载完成了,才会触发window.onload * 这也就是$(document).ready() 比 window.onload 执行早的原因 * * arguments.callee 博客里面有一篇文章 js-递归里面专门讲到了,这里不再解释了 */ document.addEventListener( "DOMContentLoaded", function () { document.removeEventListener( "DOMContentLoaded", arguments.callee, false ); callback(); } , false ); } else if (document.attachEvent) { //判断IE document.attachEvent("onreadystatechange", function () { if (document.readyState == "complete") { document.detachEvent("onreadystatechange", arguments.callee); callback(); } } ); } else if (document.lastChild == document.body) { //body已经加载完了,就直接回调了 callback(); } } } , //实现bind bind: function (type, callback) { if (document.addEventListener) { //判断火狐、谷歌 this.each(function (item, i) { item.addEventListener(type, callback, false); } ); } else if (document.attachEvent) { //判断IE this.each(function (item, i) { item.attachEvent("on" + type, callback); } ); } else { this.each(function (item, i) { //其他浏览器 egg: item.onclick = function(){ } item["on" + type] = callback; } ); } } , } ; /** * 让两个作用于不一样的对象共享一个方法,让他们的原型指向一直,即Init.prototype = _$.prototype * 那么指向之后 就可以共享this.elements 属性了。 */ _$.prototype.Init.prototype = _$.prototype; var isObj = (o) => Object.prototype.toString().call(o) === "[object Object]"; $.fn.extend = function (obj) { if (isObj(obj)) { for (var i in obj) { this[i] = obj; //注意这里的this指向是 $.prototype } } //....这里是简写 } ; _$.extend = function (obj) { if (isObj(obj)) { for (var i in obj) { this[i] = obj[i]; //注意这里的this指向是 $ } } //....这里是简写 } ; window.$ = _$; } )(window || global);
【完】
推荐学习:jQuery视频教程
以上就是你值得了解的JavaScript“继承之jquery”使用方法(代码详解)的详细内容,更多请关注其它相关文章!
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: 你值得了解的JavaScript“继承之jquery”使用方法(代码详解)
本文地址: https://pptw.com/jishu/592071.html