[英]Javascript prototype extend base-class unable to access base-class properties/methods from prototype class
I have created a javascript class TkpSlider being inspired from this w3schools page . 我已经从这个w3schools页面创建了一个javascript类TkpSlider 。 ( JSFiddle )
( JSFiddle )
var TkpSlider = function (args) {
args= args|| {};
};
var mainSwiper = new TkpSlider();
I have extended this to add some swipe ability being inspired from this page so that I can the slider works on user swipe. 我已经扩展了这个以添加一些从该页面启发的滑动功能,以便我可以在用户滑动时使用滑块。 ( JSFiddle )
( JSFiddle )
var TkpSwiper = function (args) {
TkpSlider.call(this, args);
};
TkpSwiper.prototype = Object.create(TkpSlider.prototype);
var mainSwiper = new TkpSwiper();
I separated the code so I don't get confused later from the base code and if any additional function. 我将代码分开,所以我不会在以后从基本代码和任何其他函数中感到困惑。 But with OOP I have to extend by creating a new name for it TkpSwiper , But I want to find another way to use the same name TkpSlider .
但是对于OOP,我必须通过为它创建一个新名称来扩展TkpSwiper ,但我想找到另一种使用相同名称TkpSlider的方法 。
I saw this article and tried to use prototype to extend TkpSlider in this JSFiddle (Snippet below). 我看到了这篇文章,并试图在这个JSFiddle (下面的代码段)中使用prototype来扩展TkpSlider 。 The problem is I can't access the public methods of the base class from child class.
问题是我无法从子类访问基类的公共方法。 The sample javascript in the blog I tested working though, I must be missing something with my code.
我测试过的博客中的示例javascript,我必须遗漏我的代码。 Could anyone shed some insight?
任何人都可以有所了解吗? Thanks.
谢谢。
var TkpSlider = function (args) { args= args|| {}; //private variable var btnPrev = args.btnPrev || "tkp-slide-btn-prev";//class for previous button (default: "tkp-slide-btn-prev") var btnNext = args.btnNext || "tkp-slide-btn-next";//class for next button (default: "tkp-slide-btn-next") var itemClass = args.itemClass || "tkp-slide-item"; //each item container class to slide (default: "tkp-slide-item") var isAutoSlide = args.isAutoSlide || false;//set auto slide (default: false) var autoSlideTimer = args.autoSlideTimer || 2000;//set auto slide timer when isAutoSlide is true(default: 2000) var hideBtnNav = args.hideBtnNav || false; //hide button navigation(default: false) var isRandom = args.isRandom || false; //whether next or previous slide should be random index var slideIndex = args.startIndex || 0; //start slide index number (zero based, index 0 = slide number 1, default :0) var itemNodes = document.getElementsByClassName(itemClass); var itemLength = itemNodes.length; var autoSlideInterval; //public variable this.testParentVar = "parent var"; //init function init(); function init() { if (itemLength > 0) { showSlide(); bindEvent(); isAutoSlide ? setAutoSlide() : ""; hideBtnNav ? setHideBtnNav() : ""; } else { throw "Cannot find slider item class"; } } //private function function showSlide() { if (slideIndex >= itemLength) { slideIndex = 0; } if (slideIndex < 0) { slideIndex = (itemLength - 1); } for (var i = 0; i < itemLength; i++) { itemNodes[i].style.display = "none"; } itemNodes[slideIndex].style.display = "block"; } function nextPrevSlide(n) { slideIndex += n; showSlide(); } function bindEvent() { var btnPrevNode = document.getElementsByClassName(btnPrev); if (btnPrevNode.length > 0) { btnPrevNode[0].addEventListener("click", function () { if (isRandom) { setRandomSlideIndex(); } else { nextPrevSlide(-1); } if (isAutoSlide) { clearInterval(autoSlideInterval); setAutoSlide(); } }); } else { throw "Cannot find button previous navigation"; } var btnNextNode = document.getElementsByClassName(btnNext); if (btnNextNode.length > 0) { btnNextNode[0].addEventListener("click", function () { if (isRandom) { setRandomSlideIndex(); } else { nextPrevSlide(1); } if (isAutoSlide) { clearInterval(autoSlideInterval); setAutoSlide(); } }); } else { throw "Cannot find button next navigation"; } } function setAutoSlide() { autoSlideInterval = setInterval(function () { if (isRandom) { setRandomSlideIndex(); } else { nextPrevSlide(1); } }, autoSlideTimer); } function setHideBtnNav() { document.getElementsByClassName(btnPrev)[0].style.display = "none"; document.getElementsByClassName(btnNext)[0].style.display = "none"; } function setRandomSlideIndex() { var randomIndex = Math.floor(Math.random() * itemLength); if (randomIndex == slideIndex) { setRandomSlideIndex(); } else { slideIndex = randomIndex; showSlide(); } } //public function this.nextPrevSlide = function (n) { nextPrevSlide(n); //console.log("nextPrevSlide"); }; //getter setter this.setItemClass = function (prm) { itemClass = prm; }; this.getItemClass = function () { return itemClass; }; }; //Adding touch swiper TkpSlider.prototype = function () { var self = this; var touchStartCoords = { 'x': -1, 'y': -1 }, // X and Y coordinates on mousedown or touchstart events. touchEndCoords = { 'x': -1, 'y': -1 },// X and Y coordinates on mouseup or touchend events. direction = 'undefined',// Swipe direction minDistanceXAxis = 30,// Min distance on mousemove or touchmove on the X axis maxDistanceYAxis = 30,// Max distance on mousemove or touchmove on the Y axis maxAllowedTime = 1000,// Max allowed time between swipeStart and swipeEnd startTime = 0,// Time on swipeStart elapsedTime = 0,// Elapsed time between swipeStart and swipeEnd //targetElement = document.getElementById('el'), // Element to delegate targetElements = self.getItemClass() ; init(); function init() { addMultipleListeners(targetElements, 'mousedown touchstart', swipeStart); addMultipleListeners(targetElements, 'mousemove touchmove', swipeMove); addMultipleListeners(targetElements, 'mouseup touchend', swipeEnd); } function swipeStart(e) { e = e ? e : window.event; e = ('changedTouches' in e) ? e.changedTouches[0] : e; touchStartCoords = { 'x': e.pageX, 'y': e.pageY }; startTime = new Date().getTime(); //targetElement.textContent = " "; } function swipeMove(e) { e = e ? e : window.event; e.preventDefault(); } function swipeEnd(e) { e = e ? e : window.event; e = ('changedTouches' in e) ? e.changedTouches[0] : e; touchEndCoords = { 'x': e.pageX - touchStartCoords.x, 'y': e.pageY - touchStartCoords.y }; elapsedTime = new Date().getTime() - startTime; if (elapsedTime <= maxAllowedTime) { if (Math.abs(touchEndCoords.x) >= minDistanceXAxis && Math.abs(touchEndCoords.y) <= maxDistanceYAxis) { direction = (touchEndCoords.x < 0) ? 'left' : 'right'; switch (direction) { case 'left': //targetElement.textContent = "Left swipe detected"; console.log("swipe left"); self.nextPrevSlide(1); break; case 'right': // targetElement.textContent = "Right swipe detected"; console.log("swipe right"); self.nextPrevSlide(-1); break; } } } } function addMultipleListeners(el, s, fn) { var evts = s.split(' '); var elLength = el.length; for (var i = 0, iLen = evts.length; i < iLen; i++) { if (elLength > 1) { for (var j = 0; j < elLength; j++) { el[j].addEventListener(evts[i], fn, false); } } else { el.addEventListener(evts[i], fn, false); } } } }(); var mainSwiper = new TkpSlider();
.tkp-slide { width: 100%; position: relative; } .tkp-slide .tkp-slide-item:not(:first-child) { display: none; } .tkp-slide .tkp-slide-item img { width: 100%; } .tkp-slide .tkp-slide-btn { color: #fff !important; background-color: #000 !important; border: none; display: inline-block; outline: 0; padding: 8px 16px; vertical-align: middle; overflow: hidden; text-decoration: none; text-align: center; cursor: pointer; white-space: nowrap; opacity: 0.7; } .tkp-slide .tkp-slide-btn:hover { background-color: #333 !important; } .tkp-slide .tkp-slide-btn-prev { position: absolute; top: 50%; left: 0%; transform: translate(0%, -50%); -webkit-transform: translate(0%, -50%); -ms-transform: translate(0%, -50%); } .tkp-slide .tkp-slide-btn-next { position: absolute; top: 50%; right: 0%; transform: translate(0%, -50%); -ms-transform: translate(0%, -50%); }
<section class="main-slide"> <div class="tkp-slide tkp-slide--container"> <div class="tkp-slide-item"> <a href="javascript:void(0)"> <img src="https://dummyimage.com/400x200/f2d9f2/080708&text=1" alt="Slide 1" /> </a> </div> <div class="tkp-slide-item"> <a href="javascript:void(0)"> <img src="https://dummyimage.com/400x200/f2d9f2/080708&text=2" alt="Slide 2" /> </a> </div> <div class="tkp-slide-item"> <a href="javascript:void(0)"> <img src="https://dummyimage.com/400x200/f2d9f2/080708&text=3" alt="Slide 3" /> </a> </div> <div class="tkp-slide-item"> <a href="javascript:void(0)"> <img src="https://dummyimage.com/400x200/f2d9f2/080708&text=4" alt="Slide 4" /> </a> </div> <div class="tkp-slide-item"> <a href="javascript:void(0)"> <img src="https://dummyimage.com/400x200/f2d9f2/080708&text=5" alt="Slide 5" /> </a> </div> <ul> <li class="tkp-slide-btn tkp-slide-btn-prev"> ❮ </li> <li class="tkp-slide-btn tkp-slide-btn-next"> ❯ </li> </ul> </div> </section>
Problem 1: You are not returning anything from the prototype function. 问题1:您没有从原型函数返回任何内容。 You have to return each public method as properties of the return Object.
您必须将每个公共方法作为返回Object的属性返回。
return {
initSwiper : init,
method1 : method1,
method2 : method2,
};
Problem 2: You need to set variables inside the init function. 问题2:您需要在init函数中设置变量。 Outside it this variable won't refer to TkpSlider.
在它之外, 这个变量不会引用TkpSlider。
// init();
function init() {
self=this;
var targetElements = document.getElementsByClassName(this.getItemClass());
addMultipleListeners(targetElements, 'mousedown touchstart', swipeStart);
addMultipleListeners(targetElements, 'mousemove touchmove', swipeMove);
addMultipleListeners(targetElements, 'mouseup touchend', swipeEnd);
return this;
}
Problem 3 You need to manually call the initSwiper() method to get your variables initialized when you create the TkpSlider Object. 问题3在创建TkpSlider对象时,需要手动调用initSwiper()方法来初始化变量。
var mainSwiper = new TkpSlider().initSwiper();
Then it will work as you need and you can call public methods if you need. 然后它将按您的需要工作,如果需要,您可以调用公共方法。
mainSwiper.method1();
mainSwiper.method2();
Working Snippet: 工作片段:
var TkpSlider = function(args) { args = args || {}; //private variable var btnPrev = args.btnPrev || "tkp-slide-btn-prev"; //class for previous button (default: "tkp-slide-btn-prev") var btnNext = args.btnNext || "tkp-slide-btn-next"; //class for next button (default: "tkp-slide-btn-next") var itemClass = args.itemClass || "tkp-slide-item"; //each item container class to slide (default: "tkp-slide-item") var isAutoSlide = args.isAutoSlide || false; //set auto slide (default: false) var autoSlideTimer = args.autoSlideTimer || 2000; //set auto slide timer when isAutoSlide is true(default: 2000) var hideBtnNav = args.hideBtnNav || false; //hide button navigation(default: false) var isRandom = args.isRandom || false; //whether next or previous slide should be random index var slideIndex = args.startIndex || 0; //start slide index number (zero based, index 0 = slide number 1, default :0) var itemNodes = document.getElementsByClassName(itemClass); var itemLength = itemNodes.length; var autoSlideInterval; //public variable this.testParentVar = "parent var"; //init function init(); function init() { if (itemLength > 0) { showSlide(); bindEvent(); isAutoSlide ? setAutoSlide() : ""; hideBtnNav ? setHideBtnNav() : ""; } else { throw "Cannot find slider item class"; } } //private function function showSlide() { if (slideIndex >= itemLength) { slideIndex = 0; } if (slideIndex < 0) { slideIndex = (itemLength - 1); } for (var i = 0; i < itemLength; i++) { itemNodes[i].style.display = "none"; } itemNodes[slideIndex].style.display = "block"; } function nextPrevSlide(n) { slideIndex += n; showSlide(); } function bindEvent() { var btnPrevNode = document.getElementsByClassName(btnPrev); if (btnPrevNode.length > 0) { btnPrevNode[0].addEventListener("click", function() { if (isRandom) { setRandomSlideIndex(); } else { nextPrevSlide(-1); } if (isAutoSlide) { clearInterval(autoSlideInterval); setAutoSlide(); } }); } else { throw "Cannot find button previous navigation"; } var btnNextNode = document.getElementsByClassName(btnNext); if (btnNextNode.length > 0) { btnNextNode[0].addEventListener("click", function() { if (isRandom) { setRandomSlideIndex(); } else { nextPrevSlide(1); } if (isAutoSlide) { clearInterval(autoSlideInterval); setAutoSlide(); } }); } else { throw "Cannot find button next navigation"; } } function setAutoSlide() { autoSlideInterval = setInterval(function() { if (isRandom) { setRandomSlideIndex(); } else { nextPrevSlide(1); } }, autoSlideTimer); } function setHideBtnNav() { document.getElementsByClassName(btnPrev)[0].style.display = "none"; document.getElementsByClassName(btnNext)[0].style.display = "none"; } function setRandomSlideIndex() { var randomIndex = Math.floor(Math.random() * itemLength); if (randomIndex == slideIndex) { setRandomSlideIndex(); } else { slideIndex = randomIndex; showSlide(); } } //public function this.nextPrevSlide = function(n) { nextPrevSlide(n); //console.log("nextPrevSlide"); }; //getter setter this.setItemClass = function(prm) { itemClass = prm; }; this.getItemClass = function() { return itemClass; }; }; //Adding touch swiper TkpSlider.prototype = function() { var self; var touchStartCoords = { 'x': -1, 'y': -1 }, // X and Y coordinates on mousedown or touchstart events. touchEndCoords = { 'x': -1, 'y': -1 }, // X and Y coordinates on mouseup or touchend events. direction = 'undefined', // Swipe direction minDistanceXAxis = 30, // Min distance on mousemove or touchmove on the X axis maxDistanceYAxis = 30, // Max distance on mousemove or touchmove on the Y axis maxAllowedTime = 1000, // Max allowed time between swipeStart and swipeEnd startTime = 0, // Time on swipeStart elapsedTime = 0, // Elapsed time between swipeStart and swipeEnd //targetElement = document.getElementById('el'), // Element to delegate targetElements; //this.prototype.getItemClass() ; // init(); function initSwiper() { self = this; var targetElements = document.getElementsByClassName(this.getItemClass()); addMultipleListeners(targetElements, 'mousedown touchstart', swipeStart); addMultipleListeners(targetElements, 'mousemove touchmove', swipeMove); addMultipleListeners(targetElements, 'mouseup touchend', swipeEnd); return this; } function swipeStart(e) { e.preventDefault(); e = e ? e : window.event; e = ('changedTouches' in e) ? e.changedTouches[0] : e; touchStartCoords = { 'x': e.pageX, 'y': e.pageY }; startTime = new Date().getTime(); //targetElement.textContent = " "; } function swipeMove(e) { e = e ? e : window.event; e.preventDefault(); } function swipeEnd(e) { e.preventDefault(); e = e ? e : window.event; e = ('changedTouches' in e) ? e.changedTouches[0] : e; touchEndCoords = { 'x': e.pageX - touchStartCoords.x, 'y': e.pageY - touchStartCoords.y }; elapsedTime = new Date().getTime() - startTime; if (elapsedTime <= maxAllowedTime) { if (Math.abs(touchEndCoords.x) >= minDistanceXAxis && Math.abs(touchEndCoords.y) <= maxDistanceYAxis) { direction = (touchEndCoords.x < 0) ? 'left' : 'right'; switch (direction) { case 'left': //targetElement.textContent = "Left swipe detected"; console.log("swipe left"); self.nextPrevSlide(1); break; case 'right': // targetElement.textContent = "Right swipe detected"; console.log("swipe right"); self.nextPrevSlide(-1); break; } } } } function addMultipleListeners(el, s, fn) { var evts = s.split(' '); var elLength = el.length; for (var i = 0, iLen = evts.length; i < iLen; i++) { if (elLength > 1) { for (var j = 0; j < elLength; j++) { el[j].addEventListener(evts[i], fn, false); } } else { el.addEventListener(evts[i], fn, false); } } } return { initSwiper: initSwiper }; }(); var mainSwiper = new TkpSlider().initSwiper();
.tkp-slide { width: 100%; position: relative; } .tkp-slide .tkp-slide-item:not(:first-child) { display: none; } .tkp-slide .tkp-slide-item img { width: 100%; } .tkp-slide .tkp-slide-btn { color: #fff !important; background-color: #000 !important; border: none; display: inline-block; outline: 0; padding: 8px 16px; vertical-align: middle; overflow: hidden; text-decoration: none; text-align: center; cursor: pointer; white-space: nowrap; opacity: 0.7; } .tkp-slide .tkp-slide-btn:hover { background-color: #333 !important; } .tkp-slide .tkp-slide-btn-prev { position: absolute; top: 50%; left: 0%; transform: translate(0%, -50%); -webkit-transform: translate(0%, -50%); -ms-transform: translate(0%, -50%); } .tkp-slide .tkp-slide-btn-next { position: absolute; top: 50%; right: 0%; transform: translate(0%, -50%); -ms-transform: translate(0%, -50%); }
<section class="main-slide"> <div class="tkp-slide tkp-slide--container"> <div class="tkp-slide-item"> <a href="javascript:void(0)"> <img src="https://dummyimage.com/400x200/f2d9f2/080708&text=1" alt="Slide 1" /> </a> </div> <div class="tkp-slide-item"> <a href="javascript:void(0)"> <img src="https://dummyimage.com/400x200/f2d9f2/080708&text=2" alt="Slide 2" /> </a> </div> <div class="tkp-slide-item"> <a href="javascript:void(0)"> <img src="https://dummyimage.com/400x200/f2d9f2/080708&text=3" alt="Slide 3" /> </a> </div> <div class="tkp-slide-item"> <a href="javascript:void(0)"> <img src="https://dummyimage.com/400x200/f2d9f2/080708&text=4" alt="Slide 4" /> </a> </div> <div class="tkp-slide-item"> <a href="javascript:void(0)"> <img src="https://dummyimage.com/400x200/f2d9f2/080708&text=5" alt="Slide 5" /> </a> </div> <ul> <li class="tkp-slide-btn tkp-slide-btn-prev"> ❮ </li> <li class="tkp-slide-btn tkp-slide-btn-next"> ❯ </li> </ul> </div> </section>
Prototype confusion: which this is this ?
原型混乱: 这是这个 ?
TkpSlider.prototype = function() {
console.log(this); /* this this is Child */
init();
function init() {
console.log(this); /* this this is Child, called from child context */
}
function initSwiper() {
console.log(this); /* this this is Parent, called from parent context */
}
function swipeStartEventHandler(event) {
console.log(this); /* this this is HTML element #customId*/
}
return {
initSwiper: initSwiper,
};
}();
new TkpSlider().initSwiper();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.