为什么我无法访问 class 之外的方法?

Why can't I reach the method outside the class?

我正在努力解决以下问题: 我必须基本上只使用 JS 来创建按钮。

//btn add
let button_add = document.createElement("button");
let button_add_class = button_add.className = "btn-add";
let button_add_click = button_add.setAttribute("onclick", "addBookToShoppingCart(first)");
let buttonText1 = document.createTextNode("Add to Shopping Cart");
button_add.appendChild(buttonText1);
this.mainBookScreen.appendChild(button_add);

按钮需要调用addBookToShoppingCart(first)方法,在ShoppingCartclass.

class ShoppingCart{
   addBookToShoppingCart(bookObject) {
         alert('Hello World!');
   }
}

如果单击该按钮,我会在浏览器的控制台中收到以下错误消息:

Uncaught ReferenceError: addBookToShoppingCart is not defined
at HTMLButtonElement.onclick

编辑: 我的最新代码在这里:

class ShoppingCart{
    addBookToShoppingCart(bookObject) {
        alert('Hello World!');
    }
}

class Shop {
    constructor() {
        this.shoppingCart = new ShoppingCart("Shopping Cart");
        this.mainBookScreen = document.getElementById("mainBookScreen");
    }
    addBookToScreen(book) {
    //btn add
        const button_add = document.createElement("button");
        button_add.classList.add("btn-add");
        button_add.textContent = "Add to Shopping Cart";
        button_add.addEventListener("click", function(){this.shoppingCart.addBookToShoppingCart(first)});
        this.mainBookScreen.appendChild(button_add);
    }
}

class Book {
    //book constructors
}

let first = "TEST";
let book = [];
book[0] = new Book("bla1", "bla2", "bla3");
boook[1] = new Book("ble1", "ble2", "ble3");

const shop = new Shop();

shop.addBookToScreen(book[0]);
shop.addBookToScreen(book[1]);

如果我点击按钮,浏览器中的错误消息:

Cannot read property 'addBookToShoppingCart' of undefined at HTMLButtonElement.

JS中的Class有自己的作用域。换句话说,函数 addBookToShoppingCart 在全局范围内不可用,这意味着您不能在不创建 class 的对象的情况下访问它。下面是如何访问 class

中的函数的示例
class Dog {
  function bark() {}
} 

var dog = new Dog();
dog.bark()

详情请阅读 JS 中的 scopes and class

你遇到了一些问题。

首先,不要设置具有 DOM 属性的事件,例如 onclick。虽然这可行,但它是一种更过时的方法,不符合使用 .addEventListener().

的 DOM 事件处理标准

接下来,当你只是设置一个对象的 属性 时不应该设置变量 - 你可以只设置 属性.

并且,至于调用您的方法,您需要先创建 class 的实例,然后才能使用它,当您这样做时,您必须在该实例的上下文中调用属性和方法。

class ShoppingCart{
   addBookToShoppingCart(bookObject) {
         alert('Hello World!');
   }
}

// Make an instance of the class:
let cart = new ShoppingCart();

let first = "TEST";

const button_add = document.createElement("button");

// You don't need variables to simply set properties:
button_add.classList.add("btn-add");
button_add.textContent = "Add to Shopping Cart";

// Use .addEventListener() to set up events, but the second argument takes
// a function reference, so your function invocation needs to be wrapped in 
// a reference, but within the invocation, you must call the function as
// a method of an instance of the class.
button_add.addEventListener("click", function(){cart.addBookToShoppingCart(first)});

document.body.appendChild(button_add);

根据您的编辑,问题是在 DOM 事件中 this 将引用触发事件的 DOM 对象,而不是 class 实例代码是其中的一部分。这是因为为事件处理代码创建的闭包。如果将 this 替换为实例名称,则代码如下所示:

class ShoppingCart{
    addBookToShoppingCart(bookObject) {
        alert('Hello World!');
    }
}

class Shop {
    constructor() {
        this.shoppingCart = new ShoppingCart("Shopping Cart");
        this.mainBookScreen = document.getElementById("mainBookScreen");
    }
    addBookToScreen(book) {
    //btn add
        const button_add = document.createElement("button");
        button_add.classList.add("btn-add");
        button_add.textContent = "Add to Shopping Cart";
        button_add.addEventListener("click", function(){
          // Can't use "this" to refer to the instance of the class
          // within a DOM event handler. Instead, refer to the instance
          // variable.
          shop.shoppingCart.addBookToShoppingCart(first);
        });
        this.mainBookScreen.appendChild(button_add);
    }
}

class Book {
    //book constructors
}

let first = "TEST";
let book = [];
book[0] = new Book("bla1", "bla2", "bla3");
book[1] = new Book("ble1", "ble2", "ble3");

const shop = new Shop();

shop.addBookToScreen(book[0]);
shop.addBookToScreen(book[1]);
<div id="mainBookScreen"></div>

我看到 2 个问题,其中一个是名为 boook 的变量未定义。

另一个问题在函数 addEventListener 中,this 引用按钮,就像调用 Element.shoppingCart.addBookToShoppingCart(first).

要修复它,保存一个带有 this 引用的变量并使用它,我会给你一个完整的例子:


$(function(){

    class ShoppingCart{
        
        addBookToShoppingCart(bookObject) {
            alert('Hello World!');
        }
        
    }

    class Shop {
        constructor() {
            this.shoppingCart = new ShoppingCart();
            this.mainBookScreen = document.getElementById("mainBookScreen");
        }
        addBookToScreen(book){
        //btn add
            const button_add = document.createElement("button");
            button_add.classList.add("btn-add");
            button_add.textContent = "Add to Shopping Cart";
            
            let classhere = this;
            
            button_add.addEventListener("click", function(){
                
                //this -> button element..
                
                classhere.shoppingCart.addBookToShoppingCart(first);
                
            });
            
            this.mainBookScreen.appendChild(button_add);
        }
    }

    class Book {
        //book constructors
    }

    let first = "TEST";
    let book = [];
    book[0] = new Book("bla1", "bla2", "bla3");
    book[1] = new Book("ble1", "ble2", "ble3");

    const shop = new Shop();

    shop.addBookToScreen(book[0]);
    shop.addBookToScreen(book[1]);

});