简体   繁体   English

Javascript原型扩展基类无法从原型类访问基类属性/方法

[英]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"> &#10094; </li> <li class="tkp-slide-btn tkp-slide-btn-next"> &#10095; </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"> &#10094; </li> <li class="tkp-slide-btn tkp-slide-btn-next"> &#10095; </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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM