一、继承模式
1、传统形式 --> 原型链
缺点:过多地继承了没用的属性
2、借用构造函数
call/apply,可借用别人的方式实现自己的功能。
缺点:不能继承借用构造函数的原型,且每次构造函数都要多走函数,运行效率偏低
前两种继承模式详情请参考上节--原型、原型链、call/apply
3、共享原型
缺点:不能随便改动自己的原型
Father.prototype.lastName = 'James';
function Father(){}
function Son(){}
function inherit(Target,Origin){
Target.prototype = Origin.prototype;
}
inherit(Son,Father);
var son = new Son();
console.log(son.lastName);//James
4、圣杯模式(丰满的继承)
借用中间构造函数F,实现继承。
function inherit(Target,Origin){
function F(){}
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;//找到对象的构造器
Target.prototype.uber = Origin.prototype;//找到真正继承自哪个构造函数
}
Father.prototype.lastName = 'James';
function Father(){}
function Son(){}
inherit(Son,Father);
var son = new Son();
var father = new Father();
//son.__proto__ --> new F().__proto__ -->Father.prototype
更完美的模式:参考下列代码
var inherit = (function(){
var F = function(){};
return function(Target,Origin){
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;
Target.prototype.uber = Origin.prototype;
}
}());
Father.prototype.lastName = 'James';
function Father(){}
function Son(){}
inherit(Son,Father);
var son = new Son();
var father = new Father();
二、命名空间:用来管理变量,防止污染全局,适用于模块化开发
下图是一种原始的方法,只做参考。
var org = {
department1: {
zhangsan: {},
lisi: {},
wangermazi: {}
}
}
var zhangsan = org.department1.zhangsan;
现代化解决方案:闭包,进行模块化开发
var name = 'bcd';
var initJack = (function(){
var name = 'abc';
function callName(){
console.log(name);
}
return function(){
callName();
}
}());
initJack();
方法的链式调用:
var james = {
basketball: function(){
console.log('Cool~~~!');
//return undefined;
return this;
},
football: function(){
console.log('Crazy~~~!');
return this;
},
badminton: function(){
console.log('Good~~~!');
return this;
}
}
james.basketball().football().badminton();
访问属性的另一个方法:
var obj = {name : 'abc'};
obj.name --> obj['name'],中括号里必须是字符串,直接写name就成变量了。
var obj = {
city1: {name: 'Beijing'},
city2: {name: 'Shanghai'},
city3: {name: 'Tianjin'},
city4: {name: 'Chongqing'},
sayCity : function(num){
return this['city' + num];
}
}
三、对象的枚举enumeration:
var obj = {
name : 'abc',
age : 13,
gender : 'male',
height : 180,
weight : 80,
__proto__ : {
lastname : 'James',
__proto__ : Object.prototype
}
}
for(var prop in obj){
if(obj.hasOwnProperty(prop)){
console.log(prop + " " + typeof(prop));
//console.log(obj.prop);//实质为obj['prop'],相当于访问prop属性,打印5个undefined
console.log(obj[prop]);//枚举里面必须写方括号!!!
}
}
for in循环,遍历对象(包括原型链上的属性,任何手动添加的属性,但不包括最顶端的Object.prototype的缺省属性)
obj.hasOwnProperty(prop);(返回布尔值,判断是否真实的属于自己)
in:'height' in obj(返回布尔值,属性必须写成字符串。in只能判断此对象能不能调用该属性,原型链上的也返回true)
instanceof:A instanceof B:返回布尔值,看A对象的原型链上,有没有B的原型!!!如下列代码:
function Person(){}
var person = new Person();
person instanceof Person-->true
person instanceof Object-->true
如何区分数组和对象:
[].constructor;//Array
var obj = {};
obj.constructor;//Object
[] instanceof Array;//true,只能用Array区分
var obj = {};
obj instanceof Array;//false
Object.prototype.toString.call([]);//"[object Array]"
Object.prototype.toString = function(){
//识别this
//返回相应的结果
}
var obj = {};
obj.toString();//"[object Object]"
以上内容属二哥原创,整理自 "渡一教育Javascript课程" ,一个值得推荐的"渡一教育"。