摘要:實(shí)際上,可以將其理解為某種形式的繼承。如果上下文是,則使用全局對(duì)象代替。例如的第個(gè)參數(shù)是上下文,后續(xù)是實(shí)際傳入的參數(shù)序列中允許更換上下文是為了共享狀態(tài),尤其是在事件回調(diào)中。
公開記錄學(xué)習(xí)JS MVC,不知道能堅(jiān)持多久= =。以《基于MVC的JavaScript web富應(yīng)用開發(fā)》為主要學(xué)習(xí)資料。接上一篇類的學(xué)習(xí),發(fā)現(xiàn)實(shí)在是看暈了,有些例子是能看懂在干嘛,但是不知道為什么這樣做,有的甚至看不懂,真是博大精深!
基于原型的類繼承JavaScript 是基于原型的編程語(yǔ)言,原型用來區(qū)別類和實(shí)例。原型是一個(gè)“模板”對(duì)象,它上面的屬性被用做初始化一個(gè)新對(duì)象。任何對(duì)象都可以作為另一個(gè)對(duì)象的原型對(duì)象,以此來共享屬性。實(shí)際上,可以將其理解為某種形式的繼承。
當(dāng)讀取一個(gè)對(duì)象的屬性時(shí),JavaScript 首先會(huì)在本地對(duì)象中查找這個(gè)屬性,如果沒有找到,JavaScript 開始在對(duì)象的原型中查找,若還未找到還會(huì)繼續(xù)查找原型的原型,直到查找到Object.prototype。如果找到這個(gè)屬性,則返回這個(gè)值,否則返回undefined。例如,給 Array.prototype 添加了屬性,那么所有的 JavaScript 數(shù)組都具有了這些屬性。
讓子類繼承父類的屬性的方法:
先定義一個(gè)構(gòu)造函數(shù),然后將父類的新實(shí)例賦值給構(gòu)造函數(shù)的原型:
// 父,動(dòng)物大類 var Animal = function(){}; Animal.prototype.breath = function(){ console.log("breath"); }; // 子,狗類 var Dog = function(){}; // Dog 繼承了Animal Dog.prototype = new Animal; Dog.prototype.wag = function(){ console.log("wag tail"); };
檢查繼承是否生效了:
var dog1 = new Dog; dog1.wag(); dog1.breath(); // 繼承的屬性給“類”庫(kù)添加繼承
通過傳入一個(gè)可選的父類來創(chuàng)建新類,這個(gè)可以作為創(chuàng)建類的基礎(chǔ)模板:
var Class = function(parent){ var klass = function(){ this.init.apply(this, arguments); }; // 改變klass 的原型 if (parent) { var subclass = function() { }; subclass.prototype = parent.prototype; klass.prototype = new subclass; }; klass.prototype.init = function(){}; // 定義別名 klass.fn = klass.prototype; klass.fn.parent = klass; klass._super = klass.__proto__; /* include/extend 相關(guān)的代碼…… */ return klass; };
如果將parent 傳入Class 構(gòu)造函數(shù),那么所有的子類則共享同一個(gè)原型。這種創(chuàng)建
臨時(shí)匿名函數(shù)的小技巧避免了在繼承類的時(shí)候創(chuàng)建實(shí)例,這里暗示了只有實(shí)例的屬性才會(huì)被繼承,而非類的屬性【我沒讀懂這句和上面代碼的關(guān)系,感覺已經(jīng)暈了 = =】。設(shè)置對(duì)象的proto ;屬性并不是所有瀏覽器都支持,類似Super.js的類庫(kù)則通過屬性復(fù)制的方式來解決這
個(gè)問題,而非通過固有的動(dòng)態(tài)繼承的方式來實(shí)現(xiàn)。
通過給Class 傳入父類來實(shí)現(xiàn)簡(jiǎn)單的繼承:
var Animal = new Class; Animal.include({ breath: function(){ console.log("breath"); } }); var Cat = new Class(Animal); // 用法 var tommy = new Cat;函數(shù)調(diào)用
在JavaScript中,函數(shù)和其他東西一樣都是對(duì)象。和其他對(duì)象不同的是,函數(shù)可調(diào)用。函數(shù)內(nèi)上下文,如this 的取值,取決調(diào)用它的位置和方法。
除了使用方括號(hào)可以調(diào)用函數(shù)之外,還有其他兩種方法可以調(diào)用函數(shù):apply() 和 call()。兩者的區(qū)別在于傳入函數(shù)的參數(shù)的形式。
apply() 函數(shù)有兩個(gè)參數(shù):第1個(gè)參數(shù)是上下文,第2個(gè)參數(shù)是參數(shù)組成的數(shù)組。如果上下文是null,則使用全局對(duì)象代替。例如:
function.apply(this, [1, 2, 3])
call()的第1個(gè)參數(shù)是上下文,后續(xù)是實(shí)際傳入的參數(shù)序列:
function.call(this, 1, 2, 3);
JavaScript 中允許更換上下文是為了共享狀態(tài),尤其是在事件回調(diào)中。jQuery 在其API 的實(shí)現(xiàn)中就利用了apply() 和call() 來更改上下文,比如在事件處理程序中或者使用each() 來做迭代時(shí)。
$(".clicky").click(function(){ // ‘this’指向當(dāng)前節(jié)點(diǎn) $(this).hide(); }); $("p").each(function(){ // ‘this’指向本次迭代 $(this).remove(); });
為了訪問原始上下文,可以將this 的值存入一個(gè)局部變量中,這是一種常見的模式,比如:
var clicky = { wasClicked: function(){ /* ... */ }, addListeners: function(){ var self = this; $(".clicky").click(function(){ self.wasClicked() }); } }; clicky.addListeners();
可以用apply來將這段代碼變得更干凈一些,通過將回調(diào)包裝在另外一個(gè)匿名函數(shù)中,來保持原始的上下文:
var proxy = function(func, thisObject){ return(function(){ return func.apply(thisObject, arguments); }); }; var clicky = { wasClicked: function(){ /* ... */ }, addListeners: function(){ var self = this; $(".clicky").click(proxy(this.wasClicked, this)); } };
上面的例子中在點(diǎn)擊事件的回調(diào)中指定了要使用的上下文;jQuery中調(diào)用這個(gè)函數(shù)所用的上下文就可以忽略了。實(shí)際上jQuery也包含了實(shí)現(xiàn)了這個(gè)功能的API——jQuery.proxy() :
$(".clicky").click($.proxy(function(){ /* ... */ }, this));
使用apply()和call()還有其他很有用的原因,比如“委托”。可以將一個(gè)調(diào)用委托給另一個(gè)調(diào)用,甚至可以修改傳入的參數(shù):
var App { log: function(){ if (typeof console == "undefined") return; // 將參數(shù)轉(zhuǎn)換為合適的數(shù)組 var args = jQuery.makeArray(arguments); // 插入一個(gè)新的參數(shù) args.unshift("(App)"); // 委托給console console.log.apply(console, args); } };
這個(gè)例子中首先構(gòu)建了一個(gè)參數(shù)數(shù)組,然后將參數(shù)添加進(jìn)去,最后將這個(gè)調(diào)用委托給了console.log()。arguments變量是解釋器內(nèi)置的當(dāng)前調(diào)用的作用域內(nèi)用來保存參數(shù)的數(shù)組。但它并不是真正的數(shù)組,比如它是不可變的,因此需要通過jQuery.makeArray()將其轉(zhuǎn)換為可用的數(shù)組。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/91465.html
摘要:任何函數(shù)都可以用做構(gòu)造函數(shù),構(gòu)造函數(shù)必須使用運(yùn)算符作為前綴來創(chuàng)建新的實(shí)例。當(dāng)使用關(guān)鍵字來調(diào)用構(gòu)造函數(shù)時(shí),執(zhí)行上下文從全局對(duì)象變成一個(gè)空的上下文,這個(gè)上下文代表了新生成的實(shí)例。默認(rèn)情況下,如果構(gòu)造函數(shù)中沒有返回任何內(nèi)容,就會(huì)返回當(dāng)前的上下文。 公開記錄學(xué)習(xí)JS MVC,不知道能堅(jiān)持多久= =。以《基于MVC的JavaScript web富應(yīng)用開發(fā)》為主要學(xué)習(xí)資料。 JavaScr...
摘要:基于函數(shù)進(jìn)行調(diào)用的,用來確保函數(shù)是在指定的值所在的上下文中調(diào)用的。添加私有函數(shù)目前上面為類庫(kù)添加的屬性都是公開的,可以被隨時(shí)修改。以基于的富應(yīng)用開發(fā)為主要學(xué)習(xí)資料。 控制類庫(kù)的作用域 在類和實(shí)例中都添加proxy函數(shù),可以在事件處理程序之外處理函數(shù)的時(shí)候保持類的作用域。下面是不用proxy的辦法: var Class = function(parent){ var klas...
摘要:以基于的富應(yīng)用開發(fā)為主要學(xué)習(xí)資料。下面用實(shí)現(xiàn)一個(gè)例子使用匿名函數(shù)來封裝一個(gè)作用域在頁(yè)面加載時(shí)綁定事件監(jiān)聽上面的代碼創(chuàng)建了控制器,這個(gè)控制器是放在變量下的命名空間。然后用了一個(gè)匿名函數(shù)封裝了一個(gè)作用域,以避免對(duì)全局作用域造成污染。 公開記錄學(xué)習(xí)JS MVC,不知道能堅(jiān)持多久= =。以《基于MVC的JavaScript web富應(yīng)用開發(fā)》為主要學(xué)習(xí)資料。 什么是MVC MVC 是一種設(shè)...
閱讀 3299·2021-11-23 09:51
閱讀 951·2021-09-03 10:30
閱讀 3224·2021-08-31 09:40
閱讀 3284·2019-08-30 14:22
閱讀 909·2019-08-30 14:09
閱讀 2910·2019-08-30 13:21
閱讀 3245·2019-08-28 18:03
閱讀 2865·2019-08-26 13:44