在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