对象
在jacascript里一切皆为对象,对象里有属性和行为(方法),属性有对应的值。 Object为最顶层对象。
属性分两种:
- (自身)属性:使用
this关键字定义。 - (原型)属性:定义在
prototype上。 - 特殊属性:
constructor其属性值为该对象引用(注意该属性可以被修改,请使用instanceof来检查对象类型)
prototype原型
定义:所在在原型上的属性都会被对象的实例继承。原型本身也是对象。Object.prototype为原型链最顶层。
相关方法:
- 通过原型上的
isPrototypeOf方法来验证,实例是否继承了对象的原型 技巧: - 当有较多原型属性时可使用对象的形式设置,再将
constructor设回对象的引用
function Bird () {
this.name = 'bird'
}
Bird.prototype = {
constructor: Bird, // 定义 constructor 属性
numLegs: 2,
eat: function() {
console.log("nom nom nom");
},
describe: function() {
console.log("My name is " + this.name);
}
};
// isPrototypeOf
let bird = new Bird()
Bird.prototype.isPrototypeOf(bird) // true
- 可以利用父类的方式来提取公共的原型,再通过
Object.create(object.prototype)来实例化
function Animal() { }
Animal.prototype = {
constructor: Animal,
eat: function() {
console.log("nom nom nom");
}
};
let duck = Object.create(Animal.prototype)
let beagle = Object.create(Animal.prototype)
duck.eat(); // 应该输出 "nom nom nom"
beagle.eat(); // 应该输出 "nom nom nom"
类的继承
利用原型链来实现,不同对象之间原型的继承,注意constructor重新指向子类
注意是原型链之间的继承,所以在父类的构造函数内定义的属性和行为是不会被子类继承的
function Animal() {
this.name = "foo"
}
Animal.prototype = {
constructor: Animal,
eat: function() {
console.log("nom nom nom");
}
};
function Dog() { }
Dog.prototype = Object.create(Animal.prototype)
let beagle = new Dog();
beagle.eat(); // 应该输出 "nom nom nom"
beagle.name; // undefiend 父类自身属性是不会被继承的
// 修正constructor
Dog.prototype.constructor = Dog
重写继承的方法
子类继承父类的方法后可以重写父类方法,同时又不影响到父类。
示例:
function Bird() { }
Bird.prototype.fly = function() { return "I am flying!"; };
function Penguin() { }
Penguin.prototype = Object.create(Bird.prototype);
Penguin.prototype.constructor = Penguin;
Penguin.prototype.fly = function () { return "Alas, this is a flightless bird." };
let penguin = new Penguin();
console.log(penguin.fly());
使用mixin在不同相关对象之间添加共同行为
子类继承父类固然可以解决提取相关对象的公共属性和方法,但仅限于相关对象,如何在不相关的对象间,共享这些属性和方法呢?
采用mixins方式,传入不同对象,经过处理后赋予对象属性和方法,这样有利于在不相关的对象间添加共同的行为
示例:
let bird = {
name: "Donald",
numLegs: 2
};
let boat = {
name: "Warrior",
type: "race-boat"
};
let glideMixin = function (obj) {
obj.glide = function () {
console.log('I can glide!!');
}
}
glideMixin(bird);
glideMixin(boat);
构造函数
- 定义: 用于创建一个新对象,并定义属性和行为。为创建新对象的一个最基本的方式
- 惯例:
- 首字母大写
- 使用
this关键字来设置属性和行为 - 不需要返回值
- 可接受自定义参数,用于创建各自的实例
- 用法:使用
new关键字 - 技巧:
- 使用
instanceof来验证实例的对象类型,返回布尔值 - 使用
hasOwnProperty方法来检查(自身)属性是否在对象里,返回布尔值 - 使用
prototype原型属性来实现实例间共享属性及减少重复的代码
- 使用
- 示例:
function Dog (name, color) {
this.name = name;
this.color= color;
this.numLegs = 2;
};
let dog = new Dog('foo', 'red');
dog.name // foo
dog.hasOwnProperty(name) // true
// 验证实例的对象
dog instanceof Dog // true
// 使用prototype来实现实例间共享属性
function Dog (name, color) {
this.name = name;
this.color= color;
};
Dog.prototype.numLegs = 2;
构造函数属性私用化
为了保证某些重要属性值不被外界修改,利用闭包的原理将其封存在构造函数内部,仅共内部调用,以实现变量私用化。
示例:
function Bird() {
let weight = 15;
this.getWeight = function () {
return weight;
}
}
立即调用函数表达(IIFE)
函数没有名称,也不存储在变量中。函数表达式末尾的两个括号()导致它被立即执行或调用。这种模式被叫做自执行函数表达式或者IIFE。
示例:
;(function () {
console.log('IIFE')
})();
一个自执行函数表达式(IIFE)通常用于将相关功能分组到单个对象或者是模块中。
示例:
let funModule = (function() {
return {
isCuteMixin: function(obj) {
obj.isCute = function() {
return true;
};
},
singMixin: function(obj) {
obj.sing = function() {
console.log("Singing to an awesome tune");
};
}
}
})()