I tried to craft a text slider, but I got weird result:
TypeError: HomeHeaderSlider.init is not a function
I am still learning es6 javascript.
Here are my classes:
import S from "skylake"
class HomeHeaderSlider {
init(e, t) {
function i() {
o.dataset.headerslider = h,
t()
}
let o = S.Geb.id("h-header"),
// some other variables
"h-header-arrow-btn-left" === e.target.id ? (h = 0 === c ? 5 : c - 1, d = -1) : (h = c < 5 ? c + 1 : 0, d = 1)
// some content
}
}
And here is the class extends...
class HomeController extends HomeHeaderSlider {
constructor(e) {
super();
S.BindMaker(this, ["addListeners", "getHomeHeaderSlider"]),
this.RO = new S.RO({
throttle: {
delay: 100,
atEnd: !0
}
})
}
init(e) {
let t = this
this.addListeners()
}
addListeners() {
this.listeners("add")
}
listeners(e) {
"add" === e ? this.RO.on() : this.RO.off(),
S.Listen(".h-header-arrow-btn", e, "click", this.getHomeHeaderSlider)
}
getHomeHeaderSlider(e) {
this.listeners("remove"),
HomeHeaderSlider.init(e, this.addListeners)
}
destroy(e, t) {
this.listeners("remove")
}
}
console.log(h)
// export default HomeHeaderSlider
const slidctrl = new HomeController()
slidctrl.init()
export default HomeController
It sems the code doesn't call the HomeHeaderSlider.init function.
My question is how can I call it?
HomeHeaderSlider is your class. There is no such function HomeHeaderSlider.init() on the class. The .init() method is on HomeHeaderSlider.prototoype.init or on an object instance of HomeHeaderSlider.
In this method:
getHomeHeaderSlider(e) {
this.listeners("remove"),
HomeHeaderSlider.init(e, this.addListeners)
}
it isn't entirely clear what you're trying to do there. If you want to call the base class version of .init() rather than your HomeController version of it, then you can use super.init() as in:
getHomeHeaderSlider(e) {
this.listeners("remove"),
super.init(e, this.addListeners)
}
It also looks like you may have an issue with the binding of this in this line:
S.Listen(".h-header-arrow-btn", e, "click", this.getHomeHeaderSlider)
where you need to change that to this:
S.Listen(".h-header-arrow-btn", e, "click", this.getHomeHeaderSlider.bind(this))
so that your getHomeHeaderSlider() method will have the proper value of this when it is called. When you pass this.getHomeHeaderSlider to a function, it looks on this, gets the reference to the getHomeHeaderSlider method and passes only the reference to that method. When the click handler later calls your method, there's no connection at all to the right object so the value of this is lost. Using .bind() the way I showed allows you to make sure the proper value of this stays connected to the method call. This is needed when passing a reference to a method of an object that is going to get called by some other agent that doesn't know anything about your object.
Related
Apologies if this is a newbie question but I'm learning how to use classes in JavaScript and am running into something I'm not sure is possible. Maybe my syntax is incorrect or there's a better way to go about this.
I have 2 files, each contain a class to construct an object which I'm calling in a third file (my questions are below this sample JS):
file1
import { Second } from "./file2";
class First {
constructor(
parameter1,
parameter2
) {
this.parameter1 = parameter1;
this.parameter2 = parameter2;
}
method1() {
this.parameter1 = this.parameter1 + " " + Second.parameterA
return this.parameter1;
}
}
export { First };
file2
class Second {
constructor(
parameterA,
parameterB
) {
this.parameterA = parameterA;
this.parameterB = parameterB;
}
}
export { Second };
file3
import { First } from "./file1";
import { Second } from "./file2";
const first = new First(
"someStringForParameter1",
"someStringForParameter2"
);
const second = new Second(
"someStringForParameterA",
"someStringForParameterB"
);
console.log(first.method1());
The issue is when I call method1() in the third file I get parameter1 but parameterA is undefined in the console. I'm not sure why this is the case. Is this a legal use of imported classes within another class?
I've tried importing the files in different orders (not surprised that didn't work) and moving the the Second class into the same file as the First class. I'm able to console.log() all parameters of the First and Second class from the third file successfully but the method I'm calling only returns "someStringForParameter1 undefined". My goal is for console to state "someStringForParameter1 someStringForParameterA". There are no errors in console and the linter (ESLint) I'm using in VS Code isn't highlighting anything. Any help on this would be much appreciated!
The issue doesn't have anything to do with modules. It's Second.parameterA - that will reference a property directly on the Second class, but no such property exists.
To see it when you reference Second.parameterA, you'd have to do
class Second {
static parameterA = 'something'
or, after the class definition
Second.parameterA = 'something';
But if you want the argument passed into Second to be shown, you'll have to get First to have a reference to that Second instance somehow - perhaps with a parameter to method1, like:
method1(secondInstance) {
this.parameter1 = this.parameter1 + " " + secondInstance.parameterA
return this.parameter1;
}
console.log(first.method1(second));
class First {
constructor(
parameter1,
parameter2
) {
this.parameter1 = parameter1;
this.parameter2 = parameter2;
}
method1(secondInstance) {
this.parameter1 = this.parameter1 + " " + secondInstance.parameterA
return this.parameter1;
}
}
class Second {
constructor(
parameterA,
parameterB
) {
this.parameterA = parameterA;
this.parameterB = parameterB;
}
}
const first = new First(
"someStringForParameter1",
"someStringForParameter2"
);
const second = new Second(
"someStringForParameterA",
"someStringForParameterB"
);
console.log(first.method1(second));
Or pass in the instance when calling First's constructor, or somehing like that.
Please check the following Object Structure:
var obj_parent = {
obj_child : {
obj_child_var : 15,
fnc : function() {
let self = this;
alert('Called : obj_parent>fnc() | obj_child_var : '+self.obj_child_var);
obj_parent.obj_fnc();
}
},
obj_fnc : function() {
alert('Called : obj_parent>obj_fnc();');
}
};
$(function() {
obj_parent.obj_child.fnc();
});
Test code at Codepen , just click the 'Click Here' button for testing.
At line#7, obj_parent.obj_child.fnc() is calling function obj_parent.obj_fnc() which is from it's parent's parent.
If it was not parent's parent, I could use 'this' to access(like 'obj_child_var' was accessed in lines #5,#6) the function.
Problem here is, if I have to rename 'obj_parent', I will have to rename it everywhere inside it.
What will be the best way to restructure the code where any child or more childs inside them can access any other child from the top root of the object without using it's direct name('obj_parent') but more of a generic way.
like: let self_root = pointer to the 'obj_parent';
And use this self_root instead of 'obj_parent' inside every level, everywhere inside 'obj_parent';
Here I want to keep the entire code compact inside: obj_parent = {..Everything..}
And don't want to put any code of 'obj_parent' outside of it, like using:
obj_parent.prototype.* * * = * * *;
Is there any suggestions on the best way to achieve this by restructuring the codes only inside obj_parent= {...}?
In short I am looking for something like the following inside obj_parent.obj_child.fnc():
...
fnc : function() {
let root_obj_pointer = this.parent;// Points to 'obj_parent';
root_obj_pointer.obj_fnc();// Instead of obj_parent.obj_fnc();
}
...
So that I do not have to rename the 'obj_parent' in obj_parent.obj_fnc(); if the root 'obj_parent' ever gets renamed.
Problem here is, if I have to rename 'obj_parent', I will have to rename it everywhere inside it.
I would use an IIFE instead, so that you can give the object whatever name you want inside the IIFE's scope, and return the object - then, you can rename the outer variable name from obj_parent to whatever you want without problems:
const parentVariableName = (() => {
const obj_parent = {
obj_child : {
obj_child_var : 15,
fnc : function() {
let self = this;
alert('Called : obj_parent>fnc() | obj_child_var : '+self.obj_child_var);
obj_parent.obj_fnc();
}
},
obj_fnc : function() {
alert('Called : obj_parent>obj_fnc();');
}
};
return obj_parent;
})();
parentVariableName.obj_child.fnc();
Depending on your usage, you can rewrite your child function to an arrow function so the scope is the external context.
https://codepen.io/anon/pen/rZyPmz?editors=0010
var parent = {
child: {
x: 15,
fnc: () => {
let y = parent.child.x
alert('child.fnc(): ' + y)
parent.fnc(y)
}
},
fnc: function(y) {
alert('parent.fnc(): ' + y)
}
};
function btn_clicked() {
parent.child.fnc()
}
I have typescript function. Here is code
export class Step1{
constructor(){
this.begin_search();
this.results_ready();
}
private begin_search():void {
setTimeout(() => {
Searchfield.show_searchfield()
}, 100);
$('.search_box_overlay').show()
$('.search_box_overlay_top').show()
if (gon.search['search_type'] == 'package')
$('.search_box_overlay_top .package').show()
else if (gon.search['search_type'] == 'hotel')
$('.search_box_overlay_top .hotel').show()
else
$('.search_box_overlay_top .air').show()
window.seach_status_task = setInterval(Itinerary.check_search_status, 2000)
window.search_loading_itineraries = false
}
And then I importing this code into pack
Like this
$(document).ready(() => {
Translation.addDict(gon.translations);
Track.initialize();
new Searchfield();
if (!gon.search['searched']) {
Step1.begin_search();
}
if (gon && gon.search['id'] && $('.offer_hotel_addon').length > 0) {
check_status();
}
});
But when I run project, I have this error.
WEBPACK_IMPORTED_MODULE_3__components_step1.a.begin_search is not a function
Where can be problem and how I need to fix it?
The code defines begin_search as an instance method (a part of an instance), but is trying to use them as if they were static (a part of the class itself). Mark the method as static so that it belongs to the Step1 class itself:
private static begin_search():void {
See the handbook for more info on static methods. I'd also remove the this.begin_search(); call from the constructor as well. When the method is static, it doesn't exist on this anymore.
i have this simple class:
function Page(u,o) {
this.o = o;
this.gen(u);
}
Page.prototype = {
gen:function(u) {
if(u ==='index.php') new test(this.o);
}
}
new Page('index.php',{data:"just for test"});
Is there a way to use Object.create(this); instead of new test(this.o); so that the test class can have access to this.o? and not spawn new instances of test every time? As you see i don't use var x = new ... because i don't need it.
test class just use the this.o to append some data in a div element, nothing is returned.
Thanks
Instead of using a class, just make test a normal function (if it is not already) and drop the "new". For that matter, since it looks like you don't do anything with the Page class either, make that a straight function as well:
function page(u, o) {
if (u === 'index.php') {
test(o);
}
}
Okay so I have an object and I want to apply a callback function to all of the methods in the object. This is what I have tried so far:
var namespace = {
foo : 'bar',
foobar : function() { console.log('call from foobar!')},
someFunc : function() { console.log('call from someFunc!')},
someFunc2 : function() { console.log('call from someFunc2!')}
}
var logger = {
_callback : function () {
console.log('call from logger!',arguments);
}
}
for (var m in namespace) {
if ( namespace.hasOwnProperty(m) && (typeof namespace[m]=='function') ) {
logger[m] = namespace[m];
namespace[m] = function() {
logger._callback(arguments);
logger[m].apply(this, arguments);
}
}
}
namespace.foobar('foo');
namespace.someFunc('bar');
namespace.someFunc2('bar2');
This is what is getting logged to the console:
call from logger! [["foo"]]
call from someFunc2!
call from logger! [["bar"]]
call from someFunc2!
call from logger! [["bar2"]]
call from someFunc2!
As you can see, for some reason all 3 methods of namespace are outputting 'call from someFunc2! which is wrong. I'm not sure what the issue here is.. what am I doing wrong?
Try
for (var m in namespace) {
if ( namespace.hasOwnProperty(m) && (typeof namespace[m]=='function') ) {
logger[m] = namespace[m];
(function(index){
namespace[index] = function() {
logger._callback(arguments);
logger[index].apply(this, arguments);
};
})(m);
}
}
otherwise the namespace[m] = function(){} will use whatever m is last
There's just one "m". The code inside that function you create in the for loop references the "live" value of "m", not a value frozen at the point the function was created. The last value it takes on is name "someFunc2", so that's the one that's called.
Step by step:
You create the "namespace" and "logger" objects.
The loop runs. The variable "m" takes on the successive values of the properties in the "namespace" object, and creates a new function for each relevant property of that object.
At the end of the loop, "m" has the value "someFunc2".
You call one of the "namespace" functions. That'll be a call to one of the functions created in the loop. That function will in turn call the "_callback" function. And now the important key point: it references a property of the "logger" object using the value of "m". What is the value of "m"? It's "someFunc2".