js本身不是面向對象語言,在我們實際開發中其實很少用到面向對象思想,以前一直以為當要復用的時候才封裝成對象,然而隨著現在做的項目都后期測試階段發現面向對象的作用不僅僅只是復用,可能你們會說面向對象還有繼承,多態的概念,但在javascript里面多態的概念是不存在,而繼承由于web頁面的必須先下載js在運行導致js的繼承不能像后臺那么靈活而且js沒有重載以及重寫不方便(而且js中重寫的意義不是很大),所以在js中很少用到面向對象,可能在一些插件中會看到對象的寫法,寫js的都會有同樣的感覺在寫一個插件的時候一般是先用面相過程把插件功能寫出來,然后在重構改成對象的方法.但在實際項目開發中要求時間進度和開發成本很少會有那么寬松的時間讓你先用面向過程實現功能在重構.實際開發中我們基本都是用面相過程寫完就直接提交了.
這種寫法發現一個問題就是,當你把這個頁面的寫完了之后過一段時間突然這個頁面的功能需求或是頁面布局要調整,你在看這個頁面的代碼,一下很難快速的把整個頁面的代碼邏輯步驟梳理清楚,我相信很多寫前端都要同感吧! 舉個例子:我幾年前寫的放大鏡插件,現在我在放出來發現我寫的這個插件在谷歌瀏覽器第一次渲染的時候沒有效果,代碼如下:
/// <reference path="../jquery11.js" />(function ($) {$.fn.extend({jqoom: function (potions) {var settings = {width: 350,height: 350,position: "right"}if (potions) {$.extend(settings, potions);}var ImgUrl = $("img", this).attr("src");var ImgMinWidth = $("img", this).width();var ImgMinHeigth = $("img", this).height();var ImgWidth = 0;var ImgHeight = 0;var de = true;$(this).hover(function (e) {}, function () {$("#jqoomz").remove();$(document).unbind("mousemove");$("#jqoomy").remove();de = true;});$("img", this).hover(function (e) {var pagex = e.x || e.pageX;var pagey = e.y || e.pageY;var pagex1 = 0;var pagey1 = 0;var leftcha = 0;var topcha = 0;_this = $(this).parents("div");if ($("#jqoomz").length == 0) {_this.after("<div id='jqoomz'></div>");var obj = new Image();obj.src = ImgUrl;obj.onload = function () {if (de && obj.height > 0) {de = false;ImgWidth = obj.width;ImgHeight = obj.height;finder.call(_this.find("img")[0]);}};$("#jqoomz").width(settings.width).height(settings.height).offset({left: $(_this).outerWidth() + $(_this).offset().left,top: $(_this)[0].offsetTop}).append($("<img></img>").attr("src", ImgUrl));if (de && obj.height > 0) {de = false;ImgWidth = obj.width;ImgHeight = obj.height;finder.call(this);}}function mover(event) {var pagex2 = event.x || event.pageX;var pagey2 = event.y || event.pageY;if (parseInt(pagex2 + leftcha) <= parseInt($(_this).width() + $(_this).offset().left) && pagex2 >= leftcha + $(_this).offset().left) {$(this).offset({left: pagex2 - leftcha});} else {if (parseInt(pagex2 + leftcha) > parseInt($(_this).width() + $(_this).offset().left) && pagex2)$(this).offset({left: $(_this).width() + $(_this).offset().left - leftcha * 2});else$(this).offset({left: $(_this).offset().left});}if (parseInt(pagey2 + topcha) <= parseInt($(_this).height() + $(_this).offset().top) && pagey2 >= topcha + $(_this).offset().top) {$(this).offset({top: (pagey2 - topcha)});//document.getElementById("move").style.top = (pagey2 - (this.pagey - this.divtop)).toString() + "px";} else {if (parseInt(pagey2 + topcha) > parseInt($(_this).height() + $(_this).offset().top))$(this).offset({top: ($(_this).height() + $(_this).offset().top - topcha * 2)});//document.getElementById("move").style.top = (this.height - this.divHeight).toString() + "px";else$(this).offset({top: $(_this).offset().top});//document.getElementById("move").style.top = "0px"}var bilx = ($(this).offset().left - $(_this).offset().left) / (ImgMinWidth / ImgWidth);var bily = ($(this).offset().top - $(_this).offset().top) / (ImgMinHeigth / ImgHeight);$("#jqoomz img").css({"margin-left": -bilx, "margin-top": -bily});}function finder() {if (parseFloat($(this).offset().top + $(this).height() - (ImgMinHeigth / ImgHeight * ImgMinHeigth)) >=parseFloat(pagey - ImgMinHeigth / ImgHeight * ImgMinHeigth / 2) && parseFloat(pagey - ImgMinHeigth / ImgHeight * ImgMinHeigth / 2) >=parseFloat($(this).offset().top)) {pagey1 = (pagey - ImgMinHeigth / ImgHeight * ImgMinHeigth / 2);} else {if ((pagey - ImgMinHeigth / ImgHeight * ImgMinHeigth / 2) < $(this).offset().top) {pagey1 = $(this).offset().top;} else {pagey1 = ($(this).offset().top + $(this).height() - (ImgMinHeigth / ImgHeight * ImgMinHeigth));}}if (($(this).offset().left + $(this).width() - ImgMinWidth / ImgWidth * ImgMinWidth) >=(pagex - ImgMinWidth / ImgWidth * ImgMinWidth / 2) && (pagex - ImgMinWidth / ImgWidth * ImgMinWidth / 2) >=$(this).offset().left) {pagex1 = (pagex - ImgMinWidth / ImgWidth * ImgMinWidth / 2);} else {if ((pagex - ImgMinWidth / ImgWidth * ImgMinWidth / 2) < $(this).offset().left) {pagex1 = $(this).offset().left;} else {pagex1 = ($(this).offset().left + $(this).width() - ImgMinWidth / ImgWidth * ImgMinWidth);}}leftcha = ImgMinWidth / ImgWidth * ImgMinWidth / 2;topcha = ImgMinHeigth / ImgHeight * ImgMinHeigth / 2;if ($("#jqoomy").length == 0) {$(this).after("<div id='jqoomy'></div>").siblings("#jqoomy").addClass("jqoomy").show().width((ImgMinWidth / ImgWidth * ImgMinWidth)).height((ImgMinHeigth / ImgHeight * ImgMinHeigth)).offset({top: pagey1,left: pagex1});}$(document).on("mousemove", $.proxy(mover, $("#jqoomy")));}}, function () {});}});})(jQuery);html:
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title></title><script src="jquery11.js"></script><script src="OppJqoom.js"></script><style type="text/css">.jqoom{width: 350px;height: 350px;border: solid 1px #DFDFDF;z-index: 10;}.jqoom img{cursor: pointer;z-index: 10;max-height: 350px;max-width: 350px;}.jqoomy{background-color: white;position: relative;z-index: 999;opacity: 0.5;cursor: pointer;border: solid 1px #DFDFDF;}#jqoomz{border: solid 1px #DFDFDF;position: absolute;overflow: hidden;}.lef{border: 1px solid #DFDFDF;display: block;height: 72px;line-height: 72px;text-align: center;text-decoration: none;width: 10px;background-color:#EBEBEB;float:left;}.lef:hover{color:red;}.jqooz{float:left;width:352px;margin-top:20px;}.jqooz ul{float: left;margin: 0;padding: 0;width:328px;height:72px;}.jqooz ul li{display: inline;list-style: none outside none;margin: 0 10px;}.jqooz ul li img{border: 1px solid #DFDFDF;max-height: 72px;max-width: 120px;}.jqooz ul li img:hover{border: 1px solid #ff6600;}</style><script type="text/javascript">$(function () {$(".jqoom").jqoom();});</script></head><body><div class="jqoom"><img src="b3.jpg" /></div><div class="jqooz"><a href="javascript:void(0)" class="lef"><</a><ul><li><a><img src="b3.jpg" /></a></li></ul><a href="javascript:void(0)" class="lef">></a></div></body></html>效果:

現在我要修改這個插件為什么在谷歌瀏覽器第一次加載的時候沒有效果,那我要重新跟著代碼來梳理放大鏡里面的整個功能步驟,這個放大鏡的功能還不是很復雜,在實際項目中各種函數回調嵌套,取數,數據處理,顯示,頁面的動態效果都交織在onload或是ready里面你要花幾個小時甚至一整天來梳理你要修改頁面的代碼邏輯,而且還未必能梳理的全面,所以經常會有前端同事在隔了一段時間給之前寫的頁面添加注釋的時候說我自己寫代碼都開始看不懂了.
本身javascript特點之一是事件監聽函數回調,這是它優點,nodejs作者之所以選擇js其中一個原因就是javascript的事件監聽函數回調帶來的優點,但函數回調同時也帶來一個缺點就是經常出現return不出數據,典型的例子就是ajax,jQuery傳統的ajax成功之后回調success方法,當你要把這個ajax的輸出作為另一個ajax的輸入的時候你就不得不要嵌套ajax,一旦嵌套多了這個代碼的可讀性和復雜度就增加了很多!后期的維護也自然增加了難度,Promise出來之后,jQuery、angular也都紛紛加了Promise。為什么javascript在后期維護要花這么大的時間去梳理邏輯?
我們在看看后臺java或c#的語言是怎么做,典型的javaweb幾乎都是springMVC框架,C#做web毋庸置疑是.net MVC,他們都有共同的特點是c層提供給前臺頁面ajax調用的方法都是按照所需要的數據一個一個拆分的,還有相對于的m層,mvc其實是兩個維度的分層這是我個人觀點,一個維度是單個細小的功能分為view,control,model,另一個維度是整個頁面分成多個小的功能.所以你發現后臺代碼要修改其實很容易就把邏輯梳理,那前臺javascript也能不能按照整個思路來取分層呢?
這個插件沒有涉及到動態取數,所以分層的標準也不一樣,在這里我分了兩層,第一層是對鼠標移動后圖片的一系列算法,第二層是事件綁定分的一系列dom的操作,代碼如下:
/*** Created by on 2016/11/2.*/(function ($) {//構造函數邏輯主線路var OppJqoom = function (_this, potions) {this._this = _this;this.ImgUrl = $("img", this._this).attr("src");this.ImgMinWidth = $("img", this._this).width();this.ImgMinHeigth = $("img", this._this).height();this.ImgWidth ,this.ImgHeight ,this.leftcha,this.topcha;var settings = {width: 350,height: 350,position: "right"}$.extend(this,settings);if (potions) {$.extend(this, potions);}this.domOperation.Jqoomhover.call(this);this.domOperation.imghover.call(this);};OppJqoom.prototype = {// 第一層 算法層basicOperation: {/* 獲取遮罩層的top和left*/finder: function (that) {var pagey1, pagex1;if (parseFloat($(this).offset().top + $(this).height() - (that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth)) >=parseFloat(this.pagey - that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth / 2) && parseFloat(this.pagey - that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth / 2) >=parseFloat($(this).offset().top)) {pagey1 = (this.pagey - that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth / 2);} else {if ((this.pagey - that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth / 2) < $(this).offset().top) {pagey1 = $(this).offset().top;} else {pagey1 = ($(this).offset().top + $(this).height() - (that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth));}}if (($(this).offset().left + $(this).width() - that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth) >=(this.pagex - that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth / 2) && (this.pagex - that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth / 2) >=$(this).offset().left) {pagex1 = (this.pagex - that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth / 2);} else {if ((this.pagex - that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth / 2) < $(this).offset().left) {pagex1 = $(this).offset().left;} else {pagex1 = ($(this).offset().left + $(this).width() - that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth);}}that.leftcha = that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth / 2;that.topcha = that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth / 2;that.domOperation.docMousemove.call(that);return {top: pagey1, left: pagex1};},// 放大鏡的圖片的top和leftmover: function (that) {if (parseInt(that.pagex2 + that.leftcha) <= parseInt(that._this.width() + that._this.offset().left) && that.pagex2 >= that.leftcha + that._this.offset().left) {$(this).offset({left: that.pagex2 - that.leftcha});} else {if (parseInt(that.pagex2 + that.leftcha) > parseInt(that._this.width() + that._this.offset().left) && that.pagex2)$(this).offset({left: that._this.width() + that._this.offset().left - that.leftcha * 2});else$(this).offset({left: that._this.offset().left});}if (parseInt(that.pagey2 + that.topcha) <= parseInt(that._this.height() + that._this.offset().top) && that.pagey2 >= that.topcha + that._this.offset().top) {$(this).offset({top: (that.pagey2 - that.topcha)});//document.getElementById("move").style.top = (pagey2 - (this.pagey - this.divtop)).toString() + "px";} else {if (parseInt(that.pagey2 + that.topcha) > parseInt(that._this.height() + that._this.offset().top))$(this).offset({top: (that._this.height() + that._this.offset().top - that.topcha * 2)});//document.getElementById("move").style.top = (this.height - this.divHeight).toString() + "px";else$(this).offset({top: that._this.offset().top});//document.getElementById("move").style.top = "0px"}var bilx = ($(this).offset().left - that._this.offset().left) / (that.ImgMinWidth / that.ImgWidth);var bily = ($(this).offset().top - that._this.offset().top) / (that.ImgMinHeigth / that.ImgHeight);return{left:bilx,top:bily};}},// 第二層 事件綁定層domOperation: {// 鼠標移動到圖片的一系列dom的操作imghover: function () {var that = this;$("img", this._this).hover(function (e) {this.pagex = e.x || e.pageX;this.pagey = e.y || e.pageY;var offset;var obj = new Image();obj.src = that.ImgUrl;obj.onload = function () {if (obj.height > 0) {that.ImgWidth = obj.width;that.ImgHeight = obj.height;if ($("#jqoomz").length == 0) {that._this.after("<div id='jqoomz'></div>");}offset = that.basicOperation.finder.call(that._this.find("img")[0],that);}};if ($("#jqoomz").length == 0) {that.ImgWidth = obj.width;that.ImgHeight = obj.height;that._this.after("<div id='jqoomz'></div>");}offset = that.basicOperation.finder.call(this,that);if ($("#jqoomy").length == 0) {$(this).after("<div id='jqoomy'></div>").siblings("#jqoomy").addClass("jqoomy").show().width((that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth)).height((that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth)).offset({top: offset.top,left: offset.left});}$("#jqoomz").width(that.width).height(that.height).offset({left: that._this.outerWidth() + that._this.offset().left,top: that._this[0].offsetTop}).append($("<img></img>").attr("src", that.ImgUrl));},function () {});},//鼠標在圖片上滑動的一系列dom操作docMousemove: function () {var that=this;$(document).on("mousemove", function (event) {that.pagex2 = event.x || event.pageX;that.pagey2 = event.y || event.pageY;var offset=that.basicOperation.mover.call($("#jqoomy"),that);$("#jqoomz img").css({"margin-left": -offset.left, "margin-top": -offset.top});});},//鼠標移除圖片的一系列dom操作Jqoomhover:function () {this._this.hover(function (e) {}, function () {console.log(111);$("#jqoomz").remove();$(document).unbind("mousemove");$("#jqoomy").remove();});}}};$.fn.extend({jqoom: function (potions) {return new OppJqoom(this, potions);}})})(jQuery);然后加上簡單的注釋感覺頁面的邏輯步驟就很清晰了,當然這種寫法一種比較麻煩的就是this的用法,對象中嵌套對象調用里面的方法this是指向自己的對象.
在實際開發中我們可以分為數據讀取層,數據處理層,以及dom動態效果層,如果業務比較繁雜也可以在分個數據展現層.
以上所述是小編給大家介紹的JavaScript面向對象分層思維全面解析,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!
新聞熱點
疑難解答