第一种、JavaScript 事件模型
JavaScript 事件模型是 JavaScript 中用于处理事件的机制。它定义了事件的类型、事件的传播方式以及如何处理事件。
事件类型
JavaScript 中有许多类型的事件,例如:
- 鼠标事件:单击、双击、鼠标移动等
- 键盘事件:按键按下、按键抬起等
- 表单事件:提交、重置等
- 窗口事件:加载、卸载等
事件传播
当事件发生时,它会从事件目标开始传播到事件目标的祖先元素,直到到达 document 对象。这个过程称为事件冒泡。
可以使用 stopPropagation()
方法来阻止事件冒泡。
事件处理
可以使用以下方式来处理事件:
- 使用事件监听器:可以使用
addEventListener()
方法来添加事件监听器,并使用removeEventListener()
方法来删除事件监听器。 - 使用事件属性:可以使用
event
对象来获取事件的信息。
以下是一个使用事件监听器的示例:
HTML
<button onclick="myFunction()">Click me</button>
JavaScript
function myFunction() {
alert("Hello world!");
}
这个示例将创建一个按钮,单击按钮时会弹出警报框。
以下是一个使用事件属性的示例:
HTML
<button onclick="myFunction()">Click me</button>
JavaScript
function myFunction() {
alert(event.target.tagName); // "BUTTON"
}
这个示例将弹出按钮的标签名。
第二种、闭包
闭包(closure)是 JavaScript 中一个重要的概念,它允许函数访问其创建时的外部变量。
闭包的形成
闭包是在函数执行时创建的。当函数执行时,它会创建一个环境,该环境包含函数的所有局部变量以及函数创建时的外部变量。
闭包的应用
闭包可以用于许多目的,例如:
- 创建私有变量
- 创建延迟执行的函数
- 创建事件处理程序
以下是一个使用闭包创建私有变量的示例:
JavaScript
function createCounter() {
var count = 0;
function increment() {
count++;
}
function getCount() {
return count;
}
return {
increment: increment,
getCount: getCount
};
}
var counter = createCounter();
counter.increment();
counter.increment();
console.log(counter.getCount()); // 2
这个示例中,count
变量是私有的,只能通过 increment()
和 getCount()
函数访问。
以下是一个使用闭包创建延迟执行的函数的示例:
JavaScript
function createDelayedFunction(delay) {
return function() {
// Do something after delay milliseconds
};
}
var delayedFunction = createDelayedFunction(1000);
setTimeout(delayedFunction, 1000);
这个示例中,delayedFunction()
函数将在 1 秒后执行。
以下是一个使用闭包创建事件处理程序的示例:
JavaScript
function addEventListener(element, type, handler) {
function eventHandler(event) {
handler(event);
}
element.addEventListener(type, eventHandler);
}
addEventListener(document.getElementById("button"), "click", function() {
// Do something when the button is clicked
});
这个示例中,eventHandler()
函数是闭包,它可以访问 handler()
函数。
第三种、原型链
原型链是 JavaScript 中用于实现继承的一种机制。它允许对象从其原型对象继承属性和方法。
原型链的形成
每个 JavaScript 对象都有一個原型对象。原型对象是另一个对象,它包含该对象可以继承的属性和方法。
原型链的查找
当对象访问一个属性或方法时,它会首先在其自身中查找该属性或方法。如果找不到,则会沿着原型链向上查找,直到找到该属性或方法或到达原型链的末尾。
原型链的应用
原型链可以用于许多目的,例如:
- 实现继承
- 减少代码冗余
- 提高代码的灵活性
以下是一个使用原型链实现继承的示例:
JavaScript
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log("Hello, my name is " + this.name);
};
function Employee(name, department) {
Person.call(this, name);
this.department = department;
}
Employee.prototype = Object.create(Person.prototype);
var employee = new Employee("John Doe", "Sales");
employee.sayHello(); // "Hello, my name is John Doe"
这个示例中,Employee
对象继承了 Person
对象的属性和方法。
以下是一个使用原型链减少代码冗余的示例:
JavaScript
function Animal(type) {
this.type = type;
}
Animal.prototype.eat = function() {
console.log("The " + this.type + " is eating");
};
function Dog() {
Animal.call(this, "dog");
}
Dog.prototype = Object.create(Animal.prototype);
function Cat() {
Animal.call(this, "cat");
}
Cat.prototype = Object.create(Animal.prototype);
var dog = new Dog();
dog.eat(); // "The dog is eating"
var cat = new Cat();
cat.eat(); // "The cat is eating"
这个示例中,Dog
对象和 Cat
对象都继承了 Animal
对象的 eat()
方法。
以下是一个使用原型链提高代码灵活性示例:
JavaScript
function Animal(type) {
this.type = type;
}
Animal.prototype.eat = function() {
console.log("The " + this.type + " is eating");
};
function Dog() {
Animal.call(this, "dog");
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.bark = function() {
console.log("Woof!");
};
var dog = new Dog();
dog.eat(); // "The dog is eating"
dog.bark(); // "Woof!"
这个示例中,Dog
对象继承了 Animal
对象的 eat()
方法,并添加了自己的 bark()
方法。