面向对象
继承(原型链)
- JavaScript的继承是用原型辅助完成的。其思想是利用
prototype
指向另一引用类型来实现继承基类的属性和方法。
function Base() {
this.property = 'base';
}
Base.prototype.getProperty = function () {
console.log(this.property);
};
function Sub() {
this.property = 'sub';
}
Sub.prototype = new Base();
Sub.prototype.getSubProperty = function () {
console.log(this.property);
};
Sub.prototype.getBaseProperty = function() {
console.log(this.__proto__.property);
};
let sub = new Sub();
sub.getProperty();//sub
sub.getSubProperty();//sub
sub.getBaseProperty();//base
注意!要对子类追加函数或属性必须要在重写原型之后
函数式继承
var Super = { name:'super', colors:['red','blue'] }; var sup = Object.create(Super); var sub = Object.create(Super); sub.name = 'sub'; sub.colors.push('black'); console.log(sup.name);//super console.log(sup.colors);//[ 'red', 'blue', 'black' ] console.log(sub.name);//sub console.log(sub.colors);//[ red', 'blue', 'black' ]
Object.create()
是ES5加入的函数,该函数接收2个参数:- 一个用于新对象原型的对象
- [可选] 一个为新对象定义额外属性的对象
由于使用了原型,同样会有引用类型共享的问题。
这里提供一种解决方案:
- 借用构造函数
function Super(){
this.colors = ['red','blue'];
}
function Sub(){
Super.call(this);
}
let sup = new Super();
let sub = new Sub();
sub.colors.push('black');
console.log(sup.colors);//[ 'red', 'blue' ]
console.log(sub.colors);//[ 'red', 'blue', 'black' ]
这种方法的基本思想很简单,即在子类构造函数内部调用基类的构造函数,并将基类的执行作用于指定到子类中。这样在创建子类的时候调用基类的构造函数,就会在子类实例对象上执行基类所定义的所有初始化代码。
注:call()和apply()默认第一个参数可以传递函数执行的作用域
寄生组合式继承
function Super(name) { this.name = name; this.colors = ['red']; } Super.prototype.sayName = function () { console.log(this.name); }; function Sub(name, age) { Super.call(this, name); this.age = age; } function inheritPrototype(sub, sup){ let prototype = Object.create(sup.prototype); prototype.constructor = sub; sub.prototype = prototype; } inheritPrototype(Sub,Super); Sub.prototype.sayAge = function(){ console.log(this.age); }; let sup = new Super('super'); let sub = new Sub('sub',10); sub.colors.push('blue'); sub.sayName(); sub.sayAge(); console.log(sub.colors);//[ 'red', 'blue' ] console.log(sup.colors);//[ 'red' ]
私有变量
严格来讲,JavaScript中没有私有成员的概念,即所有的对象属性都是公开的。
不过在函数内部定义的变量,因为不能被函数外部访问,所以存在私有变量的概念。
function Foo() {
var name = 'private';
function privateFun() {
console.log('private func');
}
this.publicFunc = function () {
console.log('public func');
};
}
var foo = new Foo();
foo.publicFunc(); //public func
foo.privateFun(); //foo.privateFun is not a function
静态私有变量
(() => {
var t = 1;
console.log(t);
})();
console.log(t); // t is not defined
通过匿名函数,我们同样可以实现静态私有变量。