js增加原型鏈上的方法
阿新 • • 發佈:2018-11-08
對於新人來說,JavaScript的原型是一個很讓人頭疼的事情,一來prototype容易與__proto__混淆,二來它們之間的各種指向實在有些複雜,其實市面上已經有非常多的文章在嘗試說清楚,有一張所謂很經典的圖,上面畫了各種線條,一會連線這個一會連線那個,說實話我自己看得就非常頭暈,更談不上完全理解了。所以我自己也想嘗試一下,看看能不能把原型中的重要知識點拆分出來,用最簡單的圖表形式說清楚。
我們知道原型是一個物件,其他物件可以通過它實現屬性繼承。但是尼瑪除了prototype,又有一個__proto__是用來幹嘛的?長那麼像,讓人怎麼區分呢?它們都指向誰,那麼混亂怎麼記啊?原型鏈又是什麼鬼?相信不少初學者甚至有一定經驗的老鳥都不一定能完全說清楚,下面用三張簡單的圖,配合一些示例程式碼來理解一下。
增加原型鏈上的方法例項
var _self = new EditView(); $(function () { ;(function($){ var options = { fieldCode: "gfyId", url: "../../Security/selector/user/PublicServiceUserList.html?s=" + Math.random(), multi: false, code: "gfyId,gfyIdName", keyRespField: "gfyId,id", dictCode: "publicserviceName", area: ['90%','90%'] }; /*引用查詢選擇*/ function renderSelectorMy(options){ debugger; var defaults = {}; this.settings = $.extend({},defaults,options); var $domObj = $("#" + this.settings.fieldCode + "-popSelector"); this.settings.url = $domObj.attr("action") ? $domObj.attr("action") : this.settings.url; this.settings.multi = $domObj.attr("multi") ? $domObj.attr("multi") : this.settings.multi; this.settings.code = $domObj.attr("codeAndName") ? $domObj.attr("codeAndName").split(",") : this.settings.code.split(","); this.settings.keyRespField = this.settings.keyRespField ? this.settings.keyRespField.split(",") : ""; this.init(); } //為函式新增原型鏈上的方法 renderSelectorMy.prototype = { init: function(){ debugger; var _self = this, _keys = _self.settings.code; $("input[name='" + _keys[0] +"']").parent().parent().find("button").unbind('click').bind('click', function(){ var action = "_self." + $(this).attr("action"); eval(action); }); }, querySelect : function(thi,event){ debugger; var _self = this; var url = _self.settings.url; var _keys = _self.settings.code; var keyRespField = _self.settings.keyRespField; var id = keyRespField[1]; var ids = $("input[name='" + _keys[0] +"']").val(); if(url.indexOf("?") != -1) { url = url + "&" + id + "="+ids; }else { url = url + "?" + id + "="+ids; } $Core.UI.openDialog("selwind", url, { title: "列表選擇", width: _self.settings.area[0], height: _self.settings.area[1], onClose: function () { } }); }, echoSelect : function(_data){ var _self = this; var data = _data.data, _keys = _self.settings.code, _rkeys = _self.settings.keyRespField, dictName = "", dictCode = _self.settings.dictCode; $Core.DicCache.initDictionary(dictCode,function(dicts){ var _dicts = dicts; if(dicts && dicts.data){ var dictDatas = dicts.data[dictCode]; for(var i=0,len=dictDatas.length; i<len; i++){ var item = dictDatas[i]; if(data[_keys[0]] == item[_rkeys[1]]){ var itemName = item.text; dictName += itemName +","; } } $("span input:text", $("div #" + _keys[0] + "-popSelector")).val(dictName.substr(0,dictName.length-1)); }else{ $("span input:text", $("div #" + _keys[0] + "-popSelector")).val(dictName); } }) }, selectResultAfterCallback: function(checkRlt){ var _self = this, multi = _self.settings.multi; if(checkRlt.length == 0){ $Core.UI.message.warning("選請選擇資料!"); } if(!multi && checkRlt.length != 1){ $Core.UI.message.warning("單選,請選擇一條資料!"); } var _keys = _self.settings.code, code = "", name = ""; if(!_self.settings.multi){ code = checkRlt[0]['code']; name = checkRlt[0]['name']; }else{ var _code = "", _name = ""; for(var i=0,len=dataArr.length; i<len; i++){ _code += checkRlt[i]['code'] +","; _name += checkRlt[i]['name'] +","; } code = _code.substring(0,_code.length-1); name = _name.substring(0,_name.length-1); } //給input[name='']:text 賦值 $("input[name='" + _keys[0] + "']:hidden").val(code); $("span input:text", $("div #" + _keys[0] + "-popSelector")).val(name); $(".panel-tool-close").trigger('click'); } } //擴充套件jquery類方法 $.extend({ renderSelectorMyf : function(options){ return new renderSelectorMy(options); } }); })(jQuery) renderSelector = $.renderSelectorMyf({ fieldCode: "gfyId", url: "../../Security/selector/user/PublicServiceUserList.html?s=" + Math.random(), multi: false, code: "gfyId,gfyIdName", keyRespField: "gfyId,id", dictCode: "publicserviceName", area: ['90%','90%'] }); _self.renderSelectors = [renderSelector]; });
var EditView = function(){ _this = this; if(type != "add" && _this.renderSelectors){ for(var i=0,len=_this.renderSelectors.length; i<len; i++){ var renderSelector = _this.renderSelectors[i], dictDatas = $Core.DicCache.get(renderSelector.settings.dictCode); renderSelector.echoSelect(data, dictDatas); } } } $("#btnConfirm").bind('click',function(){ var $dg = $("#dglist"); var rows = $dg.datagrid("getSelections"); var renderSelectObj = parent.renderSelector; var _datas = []; for(var i=0,len=rows.length; i<len; i++){ var dataItem = {}; dataItem.code = rows[i].id; dataItem.name = rows[i].userName; dataItem.address = rows[i].address; _datas.push(dataItem); } renderSelectObj.selectResultAfterCallback(_datas); });
JS 面向物件之原型鏈
物件的原型鏈
- 只要是物件就有原型
- 原型也是物件
- 只要是物件就有原型, 並且原型也是物件, 因此只要定義了一個物件, 那麼就可以找到他的原型, 如此反覆, 就可以構成一個物件的序列, 這個結構就被成為原型鏈
- 原型鏈到哪裡是一個頭?
- 一個預設的原型鏈結構是什麼樣子的?
- 原型鏈結構對已知語法結構有什麼修正?
原型鏈的結構
- 原型鏈繼承就是利用就是修改原型鏈結構( 增加、刪除、修改節點中的成員 ), 從而讓例項物件可以使用整個原型鏈中的所有成員( 屬性和方法 )
- 使用原型鏈繼承必須滿足屬性搜尋原則
屬性搜尋原則
- 所謂的屬性搜尋原則, 就是物件在訪問屬性與方法的時候, 首先在當前物件中查詢
- 如果當前物件中儲存在屬性或方法, 停止查詢, 直接使用該屬性與方法
- 如果物件沒有改成員, 那麼再其原型物件中查詢
- 如果原型物件含有該成員, 那麼停止查詢, 直接使用
- 如果原型還沒有, 就到原型的原型中查詢
- 如此往復, 直到直到 Object.prototype 還沒有, 那麼就返回 undefind.
- 如果是呼叫方法就包錯, 該 xxxx 不是一個函式
原型鏈結構圖
-
建構函式 物件原型鏈結構圖
function Person (){}; var p = new Person();
{} 物件原型鏈結構圖
[] 陣列原型鏈結構圖
Object.prototype
對應的建構函式
- div 對應的建構函式
-
div -> DivTag.prototype( 就是 o ) -> Object.prototype -> null
var o = {
appendTo: function ( dom ) {
}
};
function DivTag() {}
DivTag.prototype = o;
var div = new DivTag();
函式的建構函式 Function
在 js 中 使用 Function 可以例項化函式物件. 也就是說在 js 中函式與普通物件一樣, 也是一個物件型別( 非常特殊 )
- 函式是物件, 就可以使用物件的動態特性
- 函式是物件, 就有建構函式建立函式
- 函式是函式, 可以建立其他物件(函式的建構函式也是函式)
- 函式是唯一可以限定變數作用域的結構