具有对象方法的javascript作用域

时间:2018-06-25 03:52:59

标签: javascript javascript-objects

我正在尝试将div与对象绑定,以使div具有可以执行的方法。我特别希望用户单击div时,它开始在屏幕上移动,然后如果您单击另一个div,它也开始移动。

由于某种原因,我在moveCarForward方法函数中的this.element未定义。

function Car(element) {
  this.element = element;
  this.element.addEventListener("click", function() {
    this.style.border = "3px solid hotpink";
    startDrive();
  }, false);

  startDrive = function() {
    this.carDrivingInterval = setInterval(moveCarForward, 3000);
  }

  moveCarForward = function() {
    this.element.style.x = this.element.offsetLeft + 10 + "px";
  }
}

var arrayCarsElements = document.getElementsByClassName("car");
var arrCar = [];

for (var i = 0; i < arrayCarsElements.length; i++) {
  arrCar[i] = new Car(arrayCarsElements[i]);
}
<div class="car" id="tesla" style="width: 50px; height: 50px; background: #ccc; margin-bottom: 10px;"></div>

4 个答案:

答案 0 :(得分:1)

How does the "this" keyword work?解释了this的工作方式。我建议您检查一下。

在这种情况下,有必要与您的Object进行交互,同时保留其引用。在函数中定义thisnew Object())并返回到Object即可解决问题。

var Car = function(element) {
    var car = this;
    
    car.element = element;
    car.element.addEventListener("click", function() {
        car.element.style.border = "3px solid hotpink";
        car.startDrive();
    }, false);


    car.moveCarForward = function() {
        car.element.style.marginLeft = car.element.offsetLeft + 10 + "px";
    }

    car.startDrive = function() {
        car.carDrivingInterval = setInterval(car.moveCarForward, 3000);
    }

    return car;
}

var arrayCarsElements = document.getElementsByClassName("car");
var arrCar = [];

for (var i = 0; i < arrayCarsElements.length; i++) {
    arrCar[i] = new Car(arrayCarsElements[i]);
}
<div class="car" id="tesla" style="width: 50px; height: 50px; background: #ccc; margin-bottom: 10px;"></div>
<div class="car" id="fiat" style="width: 50px; height: 50px; background: #ccc; margin-bottom: 10px;"></div>

答案 1 :(得分:0)

这里有很多事情要做。首先,如注释中所述,您需要更好地控制this。箭头函数(() => {})可以提供帮助,因为它们在词法上绑定了this。您也可以显式bind()。使用事件侦听器和计时器时,您需要执行此操作,因为侦听器会调用该函数,从而更改this的含义。以下代码片段显示了两者。

将功能放在Car原型上也使管理this变得容易。

此外,我认为您的CSS有点偏离了,我将位置更改为absolute,并使用left移动了盒子。

function Car(element) {
  this.element = element;
  this.element.addEventListener("click", () => { // use arrow function or bind()
    this.element.style.border = "3px solid hotpink";
    this.startDrive();
  }, false);
}

Car.prototype.startDrive = function() {
  this.carDrivingInterval = setInterval(this.moveCarForward.bind(this), 1000); // use bind or arrow function
}

Car.prototype.moveCarForward = function() {
  this.element.style.left = this.element.offsetLeft + 10 + "px";
}


var arrayCarsElements = document.getElementsByClassName("car");
var arrCar = [];

for (var i = 0; i < arrayCarsElements.length; i++) {
  arrCar[i] = new Car(arrayCarsElements[i]);
}
<div class="car" id="tesla" style="position:absolute; left: 10px; width: 50px; height: 50px; background: #ccc; margin-bottom: 10px;"></div>
<div class="car" id="ford" style="position:absolute; top: 75px; left: 10px; width: 50px; height: 50px; background: #ccc; margin-bottom: 10px;"></div>

可能还有更多工作要做(例如单击两次时会发生什么),但是希望这可以帮助您入门。

答案 2 :(得分:0)

这是正确的代码。功能Car(element)-如果在控制台中打印“ element”,它将给出两个div。单击一个div时,必须通过startDrive(element)发送当前的div参数。

function Car(element) {
  element.addEventListener("click", function() {
    this.style.border = "3px solid hotpink";
    startDrive(element);
  }, false);

  startDrive = function(element) {
    carDrivingInterval = setInterval(function() { moveCarForward(element); }, 3000);
  }

  moveCarForward = function(element) {
    element.style.left = element.offsetLeft + 10 + "px";
  }
}

var arrayCarsElements = document.getElementsByClassName("car");
var arrCar = [];

for (var i = 0; i < arrayCarsElements.length; i++) {
  arrCar[i] = new Car(arrayCarsElements[i]);
}
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>javascript scope with object method</title>
</head>

<body>
<div class="car" id="tesla" style="position:absolute;width: 50px; height: 50px;top:10px; left: 10px; background: #ccc; margin-bottom: 10px;"></div>
<div class="car" id="bmw" style="position:absolute;width: 50px; height: 50px;top:100px; left: 10px; background: #ccc; margin-bottom: 10px;"></div>
</body>
</html>

答案 3 :(得分:-1)

您可以使用一个对象定义您的功能并返回该对象,以便您也可以从外部Car函数获得该功能(例如,如果要从外部停止汽车,则为示例)。看到我的以下代码,它具有启动/停止功能。只需运行摘要即可查看。

function Car(element) {
  var car = {
    element: element,
    running: false,
    start: function() {
      this.carDrivingInterval = setInterval(this.moveCarForward.bind(this), 1000);
      this.running = true;
    },
    stop: function(){
      clearInterval(this.carDrivingInterval);
      this.running = false;
    },
    moveCarForward: function() {
      this.element.style.left = this.element.offsetLeft + 10 + "px";
    }
  };
  
  element.addEventListener("click", function(event) {
    if(!car.running){
      this.style.border = "3px solid hotpink";
      car.start();
    }else{
      this.style.border = "3px solid red";
      car.stop();
    }
  });
  
  return car;
}
    
var arrayCarsElements = document.getElementsByClassName("car");
var arrCar = [];

for (var i = 0; i < arrayCarsElements.length; i++) {
  arrCar[i] = new Car(arrayCarsElements[i]);
}
<div class="car" id="tesla1" style="position: absolute; width: 50px; height: 50px; background: #ccc; margin-bottom: 10px;">Car 1</div>
<div class="car" id="tesla2" style="position: absolute; width: 50px; height: 50px; background: #eee; margin-bottom: 10px; left: 50px;">Car 2</div>

当我使用对象定义功能时,现在我可以完美地使用this了。