在JavaScript中,每个对象都有一个原型对象,通过原型对象可以实现属性的继承。本文将讲解JavaScript中的原型链和原型继承的高级应用。
在JavaScript中,每个对象都有一个原型对象,通过原型对象可以实现属性的继承。在查找对象属性时,如果该对象本身没有该属性,就会去它的原型对象中查找,如果还没有,就会去原型对象的原型对象中查找,直到查找到Object的原型对象,这个过程就叫做原型链。
原型链的示意图如下:
┌────────────────┐
│ Object │
└────────────────┘
▲
│
┌─────────────┐
│ Object.prototype │
└─────────────┘
▲
│
┌─────────────┐
│ Function.prototype │
└─────────────┘
▲
│
┌─────────────┐
│ Constructor.prototype │
└─────────────┘当我们访问对象a的某个属性时,如果a对象本身没有这个属性,就会去它的原型对象中查找,如果原型对象中也没有这个属性,就会去原型对象的原型对象中查找,以此类推,直到找到Object的原型对象,如果还没有找到,就会返回undefined。
在JavaScript中,原型继承是指通过原型对象实现继承。我们可以通过修改对象的原型对象来实现继承。
在JavaScript中,每个对象都有一个原型对象,通过原型对象可以实现属性的继承。在查找对象属性时,如果该对象本身没有该属性,就会去它的原型对象中查找,如果还没有,就会去原型对象的原型对象中查找,直到查找到Object的原型对象,这个过程就叫做原型链。
原型链的示意图如下:
┌────────────────┐
│ Object │
└────────────────┘
▲
│
┌─────────────┐
│ Object.prototype │
└─────────────┘
▲
│
┌─────────────┐
│ Function.prototype │
└─────────────┘
▲
│
┌─────────────┐
│ Constructor.prototype │
└─────────────┘当我们访问对象a的某个属性时,如果a对象本身没有这个属性,就会去它的原型对象中查找,如果原型对象中也没有这个属性,就会去原型对象的原型对象中查找,以此类推,直到找到Object的原型对象,如果还没有找到,就会返回undefined。
下面是一个原型继承的例子:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.say = function() {
console.log('My name is ' + this.name + ', I am ' + this.age + ' years old.');
};
function Student(name, age, grade) {
Person.call(this, name, age);
this.grade = grade;
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.study = function() {
console.log('I am studying in grade ' + this.grade + '.');
};
var stu = new Student('Tom', 18, 'Grade 3');
stu.say();
stu.study();在上面的例子中,我们定义了一个Person构造函数和一个Student构造函数,Student构造函数通过调用Person构造函数来实现继承,然后再将Student的原型对象设置为Person的原型对象,这样就实现了继承。最后我们创建了一个stu对象,并调用了它的say和study方法。
在JavaScript中,函数是一等公民,它们可以像变量一样赋值、传递和使用。下面介绍一些函数的细节用法参数。
在JavaScript中,每个函数都有一个arguments参数,它包含了所有传递给函数的参数,可以通过它来访问这些参数。arguments参数是一个类数组对象,可以使用下标来访问其中的元素。
下面是一个使用arguments参数的例子:
function sum() {
var total = 0;
for (var i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
console.log(sum(1, 2, 3, 4, 5));在上面的例子中,我们定义了一个sum函数,它使用了arguments参数来计算传递给它的所有参数的总和。
在JavaScript中,我们可以使用apply和call方法来调用函数,并且可以指定函数中的this指向哪个对象。
下面是一个使用apply方法的例子:
function sayName() {
console.log('My name is ' + this.name);
}
var person = {
name: 'Tom'
};
sayName.apply(person);在上面的例子中,我们定义了一个sayName函数和一个person对象,然后使用apply方法调用sayName函数,并将this指向person对象。
在JavaScript中,我们可以使用bind方法来创建一个新的函数,并指定函数中的this指向哪个对象,同时也可以预设部分参数。
下面是一个使用bind方法的例子:
function add(a, b) {
return a + b;
}
var addFive = add.bind(null, 5);
console.log(addFive(3));在上面的例子中,我们定义了一个add函数,然后使用bind方法创建了一个新的函数addFive,并预设了第一个参数为5。当我们调用addFive函数时,它会将第一个参数设置为5,并将第二个参数设置为传递给它的参数,最后返回它们的和。
下面是一个使用原型继承和函数细节用法参数的案例:
function Animal(name) {
this.name = name;
}
Animal.prototype.say = function() {
console.log('I am ' + this.name);
};
function Dog(name) {
Animal.call(this, name);
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
console.log('Woof! Woof!');
};
function Cat(name) {
Animal.call(this, name);
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.meow = function() {
console.log('Meow! Meow!');
};
function AnimalFarm() {
this.animals = [];
}
AnimalFarm.prototype.addAnimal = function(animal) {
this.animals.push(animal);
};
AnimalFarm.prototype.listAnimals = function() {
for (var i = 0; i < this.animals.length; i++) {
this.animals[i].say();
if (this.animals[i] instanceof Dog) {
this.animals[i].bark();
}
if (this.animals[i] instanceof Cat) {
this.animals[i].meow();
}
}
};
var farm = new AnimalFarm();
var dog = new Dog('Rufus');
var cat = new Cat('Fluffy');
farm.addAnimal(dog);
farm.addAnimal(cat);
farm.listAnimals();在上面的例子中,我们定义了一个Animal构造函数和一个AnimalFarm构造函数,AnimalFarm构造函数中包含了两个方法addAnimal和listAnimals。我们还定义了一个Dog构造函数和一个Cat构造函数,它们都继承了Animal构造函数。我们创建了一个AnimalFarm对象,并向其中添加了一个Dog对象和一个Cat对象,最后调用listAnimals方法打印动物的名字和声音。
本文为翻滚的胖子原创文章,转载无需和我联系,但请注明来自猿教程iskeys.com
