继承发展史
- 传统形式 ——>原型链
过多的继承了没用的属性
Grand.prototype.lastName = "Ji";
function Grand() {
}
var grand = new Grand();
Father.prototype = grand;
function Father() {
this.name = 'hehe';
}
var father = new Father();
Son.prototype = father;
function Son() {
}
var son = new Son();
- 借用构造函数
不能继承借用构造函数的原型
每次构造函数都要多走一个函数
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
function Student (name, age, sex, grade) {
Person.call(this, name, age, sex);
this.grade = grade;
}
var student = new Student();
- 共享原型
不能随便改动自己的原型
Father.prototype.lastName = "Deng";
function Father() {
}
function Son() {
}
Son.prototype = Father.prototype
var son = new Son();
var father = new Father();
// Father.prototype
//Father Son
抽象功能,封装函数,实现继承
function inherit(Target, Origin) {
Target.prototype = Origin.prototype;
}
inherit(Son,Father);
var son = new Son();
当改变自己的原型时,也改变了其他的原型
Father.prototype.lastName = "Deng";
function Father() {
}
function Son() {
}
function inherit(Target, Origin) {
Target.prototype = Origin.prototype;
}
inherit(Son, Father);
Son.prototype.sex = "male";
var son = new Son();
var father = new Father();
//Son.prototype和Father.prototype是同一个指向>father.sex <male
- 圣杯模式
添加个性化属性,不影响其他的原型;继承自己的原型,也继承公有的原型
function inherit(Target, Origin) {//继承封装成函数
function F() {}
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;//让son.constructor指向本身
Target.prototype.uber = Origin.prototype;//表示真正继承自Father
}
Father.prototype.lastName = "Deng";
function Father() {
}
function Son() {
}
inherit(Son, Father);
var son = new Son();
var father = new Father();
//Son.prototype.sex = "male";
//>son.sex <male
//>father.sex <undefined
//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;
}
}());
闭包的第3点应用:可以实现封装,私有化变量
function Deng(name, wife) {
var prepareWife = "xiaozhang";//私有化变量
this.name = name;
this.wife = wife;
this.divorce = function () {//方法
this.wife = prepareWife;
}
this.changePerpareWife = function(target) {//方法
prepareWife = target;
}
this.sayPreparewife = function () {//方法
console.log(prepareWife);
}
}
var deng = new Deng('deng', 'xiaoliu');
deng.divorce();
//形成闭包,divorce,changePerpareWife,sayPerparewife三个函数被保存到外部,储存了函数Deng的执行上下文AO,所以三个函数在外部可以随意存取
//>deng.prepareWife <undefined外部不可以访问私有化变量,不是对象的属性,属于闭包里的
//>deng.sayPreparewife <xiaozhang实行对象设置的方法可以访问私有化变量
命名空间
原始方法:管理变量,防止污染全局,适用于模块化开发
var org = {
department1 : {
jicheng : {
name : "abc",
age : 123,
},
xuming : {
}
},
department2 : {
zhangsan : {
},
lisi : {
}
}
}
var jicheng = org.department1.jicheng;
jicheng.name
现代化解决方案:闭包的第4点应用——模块化开发
用闭包私有化自己的变量(name),避免命名重复;
var name = 'bcd';
var init = (function () {
var name = 'abc';
function callName() {
console.log(name);
}
return function () {
callName();
}
}())
var initDeng = (function () {
var name = 123;
function callName() {
console.log(name);
}
return function () {
callName();//功能复用,提取到闭包里
}
}())
init();//abc
initDeng();//123
方法的链式调用(模仿jQuery)
var deng = {
smoke : function () {
console.log('Smoking,... xuan cool!!!');
//return undefined
return this;
},
drink : function () {
console.log('drinkin..., ye cool!');
return this;
},
perm : function () {
console.log('perming..., cool!');
return this;
}
}
deng.smoke().drink().perm().smoke().drink();//都可以执行
属性表示方法
obj.prop(属性)
obj[“prop”] (字符串形式的属性名) 运行快,不用转化
obj.name --> obj[‘name’],中括号里必须是字符串,直接写name就成变量了。
var obj = {
wife1 : {name : "xiaoliu"},
wife2 : {name : "xiaozhang"},
wife3 : {name : "xiaomeng"},
wife4 : {name : "xiaowang"},
sayWife : function (num){//方法
return this['wife' + num];//实现属性名的拼接只能用obj["prop"]
}
}
对象的枚举
var arr = [1,3,3,4,5,6,7,8,9];
// 遍历数组 枚举 enumeration
for(var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
遍历属性 for in遍历对象(包括原型链上的属性,任何手动添加的属性,但不包括最顶端的Object.prototype的缺省属性)
1.hasOwnProperty 返回布尔值,判断是否真实的属于自己的方法
var obj = {
name : '13',
age : 123,
sex : "male",
height : 180,
weight : 75
__proto__ : {
lastname : 'deng',//原型上的属性
__proto__ : Object.prototype
}
}
Object.prototype.abc = '123';//ok 包括手动添加的属性
for(var prop in obj) {//prop代表属性名(可替换) obj是固定的
if(!obj.hasOwnProperty(prop)){
//console.lgo(prop + " " + typeof(prop));//string类型
//console.log(obj.prop);//实质为obj['prop'],相当于访问prop属性,打印5个undefined
console.log(obj[prop]);//枚举里面必须写方括号!!!
}
}
//不属于自己的方法:deng 123
2.in(只能判断对象能不能调用这个属性,不能判断属性属不属于这个对象)使用少
‘height’ in obj —> true
‘lastname’ in obj —> true
3.instanceof
function Person() {
}
var person = new Person();
//A对象 是不是 B构造函数构造出来的
//看A对象的原型链上 有没有 B的原型
//A instanceof B
person instanceof Person ---> true
person instanceof Object ---> true
[] instanceof Array -->true
[] instanceof Object -->true
person instanceof Array --> false
{} instanceof Person --> false
判断变量是数组or对象?
法一:constructor
[].constructor;//Array
var obj = {};
obj.constructor;//Object
法二:instanceof
[] instanceof Array;//true,只能用Array区分
var obj = {};
obj instanceof Array;//false
法三:toString()方法
Object.prototype.toString.call([]);//"[object Array]" this 是 数组
Object.prototype.toString.call(123);//"[object Number]" this 是 数字
Object.prototype.toString.call({});//"[object Object]" this 是 对象
Object.prototype.toString = function() {
//识别this
//返回相应的结果
}
var obj = {};
obj.toString();//"[object Object]"
//obj调用toString --> this是obj