构造函数
JS 中的函数既可以是普通函数也可以是构造函数,区别在于调用方式。通过对象调用就是普通函数,通过 new 操作符就是构造函数。
var foo = function() {
name: "小明";
};
// 此时的 foo 是一个普通函数
foo();
// 此时的 foo 是一个构造函数
var bar = new foo();
new 运算符
new 是一个运算符,可以创建对象,初始化实例会调用指定的构造函数,根据传入的参数,初始化作用域中的属性。
//创建数组对象c,并初始化
var c = new Array(1, 2, 3);
var foo = function(x,y) {
//自定义函数
this.x = x; //属性x
this.y = y; //属性y
};
var b = new foo(1,2); // 实例化对象
原型
所有 JavaScript 对象都从原型继承属性和方法,我们在创建 js 的对象时,可以发现该对象已经拥有了很多自带的属性和方法了,而这些属性或方法都是从原型继承而来。原型可以让继承自它的对象共享相同的属性和方法。
// 函数的原型
function foo() {
name: "小明";
}
//这是函数的原型
foo.prototype;
// 一般对象的原型
var a = 18;
//这是对象的原型
a.__proto__;
var bar = new foo();
//这是对象的原型
bar.__proto__;
原型的属性扩展和继承
function Animal() {
console.log("this is a animal");
eat = function() {
console.log("animal could eat");
};
}
//扩展属性
Animal.prototype.breaking = function() {
console.log("animal could break");
};
//eat 继承了所有 Animal 的属性,包括扩展属性
cat = new Animal();
cat.breaking();
// 对象实例与构造函数取原型的方式不一样
console.log(cat.__proto__ === Animal.prototype); //true
constructor
constructor 表示 指向该对象的构造函数,如果该对象本来就是从构造函数实例化而来,那么 constructor 又可以指向这个构造函数本身了。
function Person() {}
console.log(Person === Person.prototype.constructor); //true
__proto__和 constructor 属性是对象所独有的.
prototype 属性是函数所独有的,因为函数也是一种对象,所以函数也拥有__proto__和 constructor 属性
原型链与继承
原型链的尽头是 null,下面通过一个经典的案例说明原型链与继承的用法
// “假设” 这是一个动物 “类”(注意这只是一个假设,实际上它并不是类),它拥有两个属性(动物名词、动物毛发颜色)
function Animal(name, color) {
this.name = name;
this.color = color;
}
// 任务1 要求扩展 Animal 的属性,使之具有 eat (吃)的特性,而且需要根据动物特性 吃相应食物(比如 狗吃肉,牛吃草)
Animal.prototype.eat = function(food) {
console.log(this.color + this.name + "吃" + food);
};
// 任务2 要求扩展动物叫声属性,使之具有 voice (叫声)的特性,而且需要根据动物特性 (比如 狗 “汪”,牛 “哞”)
Animal.prototype.barking = function(voice) {
console.log(voice);
};
// 任务3 然后在实列化一个对象,并且这个对象的叫声属性是(“哞”),动物是牛
var dog = new Animal("牛", "黑");
dog.eat("草");
dog.barking("哞");
// 任务4 再实例化一个对象,并且这个对象的叫声属性是(“汪”),动物是狗
var dog = new Animal("狗", "黑");
dog.eat("肉");
dog.barking("汪");