13、继承模式、命名空间、对象枚举

继承模式、命名空间、对象枚举

继承发展史

1.传统形式—->原型链

过多的继承了没用的属性

// son把原型链上的所有东西都继承下来的  不需要的都继承了
Gand.prototype.lastName = 'zhang'
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 Students(name, age, sex, grade, tel) {
    Person.call(this, name, age, sex);
    // Person.apply (this, [name, age, sex]);  两种方法都可以
    this.grade = grade;
    this.tel = tel;
}
var student = new Student();
每次构造函数都要多走一个函数(浪费效率)
// 每次构造函数都需要执行Student和Person这两个函数
function Person(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
}
function Student(name, age, sex, grade, tel) {
    Person.call(this, name, age, sex);
    // Person.apply (this, [name, age, sex]);  两种方法都可以
    this.grade = grade;
    this.tel = tel;
}
var student = new Student();

3.共享原型(公有原型)

共享原型
// 不通过原型链继承原型的方法(公有原型)
Father.prototype.lastName = 'cheng'
function Father() {}
function Son() {}
Son.prototype = Father.prototype // prototype是对象 可直接赋值
var son = new Son();  // 访问father.lastName输出cheng
var father = new Father();  // 访问son.lastName输出cheng 
// 说明father和son都继承了Father的原型
继承
继承的两种写法
1. function extend()
2. function inherit()  // inherit继承 也是css属性的一个值(如果子元素没设置文字属性的话,默认继承父元素的文字属性)
// font-size : inhert  // 所以子元素如果没有属性就默认继承父元素的
Father.prototype.lastName = 'cheng'
function Father() {}
function Son() {}
// origin是原始的 这是让target继承origin 传进来的是一个构造函数 因为只要是构造函数继承了 那生产的所有对象就全继承了
function inherit(Target, Origin) {  // 这是定义inherit的方法
   Target.prototype = Origin.prototype;
}
inherit(Son, Father);  // 两个构造函数共用原型  Son继承Father的
var son = new Son();
// inherit(Son, Father); 继承写这里就晚了 都已经构造完对象了 还是继承的之前的原型
不能随便改动自己的原型
// inherit继承的不足  改动的原型是共用的  一个改全部改
Father.prototype.lastName = 'cheng'
function Father() {}
function Son() {}
function inherit(Target, Origin) {
   Target.prototype = Origin.prototype;
}
inherit(Son, Father);
Son.prototype.sex = 'male';  // 给原型增加sex属性
var son = new Son();  // 访问son.sex输出male
var father = new Father();  // 访问father.sex输出male
// Son.prototype和Father.prototype指向的是一个原型 一改全改

4.圣杯模式

// F.prototype做一个中间层 继承Father的原型 Son又继承F的原型  原型只能更改自己的 所以不影响Son自己增加属性  相当于小型原型链  这里是原型 不是继承  所以不会影响(继承是共同指向一个位置 原型是copy)

function F() {}
F.prototype = Father.prototype;
Son.prototype = new F();
    提取||
        ||公式
//圣杯模式
function inherit(Target, Origin) {  // 这里定义方法
    function F() {}
    //下面两行不能调换 要先更改原型再构造对象  不能构造对象之后再换原型,如果调换了,new F()的原型就不是Origin的原型 
    Target.prototype = Origin.prototype;
    Target.prototype = new F();
    Target.prototype.constructor = Target;  // 这是为了让构造器归位  比如son访问构造器 就是它自己
    Target.propotype.uber = Origin.prototype; // 可有可无 可以知道它真正继承自谁
}
Father.prototype.lastName = 'cheng'
function Father() {}
function Son() {}
inherit(Son, Father);
var son = new Son();
var father = new Father();
Son.prototype.sex = 'male';  // 给Son增加sex属性
son.sex;  // 输出male  说明son的原型增加了sex属性
father.sex;  // 输出undefined  说明了两者互不影响
// constructor是原型的属性,而F是对象,没有这个属性,所以找F的原型 Father,prototype Father,prototype上的constructor指向Father
// son.__proto__ -->  new F().__proto__ --> Father.prototype
son.constructor;  // 输出 function Father() {} 
// 私有化变量(上面代码的更好的写法)
var inherit = (function () {
	var F = function () {};
	return function demo (Target, 0rigin) {
		F.prototype = 0rigin.prototype;
		Target.prototype = new F();
		Target.prototype.constructor = Target;
		Target.prototype.uber = 0rigin.prototype;
	}
    return demo;
}());
// 为啥形成闭包 因为隐式三步里最后一步是return this 然后函数保存在this里,最后跟踪this一起被保存到了外部

//私有化变量  通过Deng.preparewife访问结果是undefined
function Deng( name, wife) {
    var preparewife = "xiaozhang";
    this. name = name;
    this.wife = wife;
    this.divorce = function () {
    	this.wife = preparewife;
    }
    this.changePreparewife = function (target){
  	  preparewife = target;
    }
    this.sayPraprewife = function ( ) {
   	 console.log(preparewife);
    }
}
var deng = new Deng( 'deng' , 'xiaoliu' );

命名空间

管理变量

// 防止变量名重复 把所有的变量名都放在一个全局对象中
// 现在不这么用了 了解一下就好
var org = {
    department1 : {
        jicheng : {
      	  name : "abc" ,
           age : 123
        },
        xuming : {
      }
    },
    departmeng2 : {
        zhangsan : {
        },
        lisi : {
        }
  	}
}

// 引用变量
var jicheng = org.department1. jicheng;
jicheng.name

防止污染全局、适用于模块化开发

// 闭包拥有独立词法作用域,不会污染全局作用域
var init = ( function () {
    var name = 'abc ';
    function callName( ) {
  	  console.log( name) ;
    }
    return function () {
  	  callName( );
    }
}())

init();  // 执行init(初始化的意思)就相当于调用函数里面的东西

// 这个函数里面的变量名和上面的互不影响 其实就是局部变量
var initDeng = (function ( ) {
    var name = 123;
    function callName( ) {
   	 console.log( name) ;
    }
    return function () i
  	  callName( );
    }
}())

问题

如何实现链式调用模式(模仿jQuery)
<!--jQuery调用css方法-->
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script type="text/javascript" src="jQuery.js"></script>
</ head>
<body>
    <div></div>
    <script type="text/javascript">
    $( 'div').css('background-color','red').width(100).height(100).html(123).css('position','absolute' ).css( 'left', '100px').css( 'top','100px');
	</script>
</body>
obj.eat().smoke().drink().eat().sleep();
<!--链式调用-->
var deng = {
    smoke : function () {
   		console.log( ' Smoking, .. . xuan cool! ! ! ');
      	 return this;
    },
    drink : function ( ) {
   		console.log( ' drinking. .., ye cool! ' );
		return this;
    },
    perm : function () {
		console.log( ' preming. . . , cool! ');
		return this;
    }
}

// deng.smoke().drink();这样写会报错  因为deng.smoke()没有返回值 所以有个隐式的返回undefined  第二个方法就相当于undefined.drink() 这会报错  所以想每个函数链式调用 就需要每个函数之后都返回this(函数本身)

deng.smoke().drink().prem() // 返回this之后就可以链式调用

属性表示方法

obj.prop
var obj = {
	name : "abc"
}
obj.name ----> obj ['name']  // obj隐式转换过程 所以obj.name和obj['name']都可以访问到name这个变量  注意第二种访问方式是字符串 要加引号 第二种方式更灵活 因为字符串可以拼接

image-20221005152801358

obj[“prop”]
// obj.prop的使用  实现属性名的拼接
var deng = {
    wife1 : {name : "xiaoliu"},
    wife2 : {name : "xiaozhang"},
    wife3 : {name : "xiaomeng"},
    wife4 : {name : "xiaowang"},
    saywife : function (num){
    	return this [ 'wife' +num];  // 属性名拆分成wife+num
    }
}

image-20221005153420101

对象枚举

.// 遍历数组
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

var obj = {
    name : '13',
    age : 123,
    sex : "male" ,
    height : 180,
    weight : 75
}
// prop in obj 就是遍历obj中所有的属性 有多少个属性就遍历多少次 在每次循环的时候  会把属性名放在prop这个对象里面 prop也可以自定义别的名字  换成key也行  prop相当于i
for(var prop in obj) {
	// console.log(prop + "" + typeof(prop) );
	// console.log(obj.prop);  这么写打印undefined 因为这样是在obj中找属性名是prop的属性值进行打印  然而没这个属性 所以打印undefined  
    console.log(obj.[prop]); // 加[]之后prop才代表不同的变量 每次都把不同的属性放到prop里面 然后打印属性值  切记不要加引号
}

var obj1 = {
    a : 123,
    b : 234,
    c : 345
}
var key;
for(key in obj1) {
	obj1.key ++;
}
var obj = {
    name : '13',
    age : 123,
    sex : "male",
    height : 180,
    weight : 75,
    __proto__: {
        lastName : "deng"
	}
}
for(var prop in obj) {
    // 这里打印会把__proto__(原型)也打印出来
	console.log(obj[prop] ); 
}

hasOwnProperty

判断是不是自身的属性。

var obj = {
    name : '13',
    age : 123,
    sex : "male",
    height : 180,
    weight : 75,
    __proto__: {
        lastName : "deng"}
}

for(var prop in obj) {
    // 判断是不是自身的属性  是就打印  不是就不打印 __proto__是原型  所以不会打印
    if(obj.hasOwnProperty(prop)) {
        console.log(obj[prop]); 
    }
}

in

in判断的是这个对象中能不能访问到这个属性,所以原型中的属性也算它的。

'height' in obj ==> true

'lastName' in obj ==> true
instanceof
function Person( ) {}
var person = new Person( );
var obj = {};

// 官方:A对象是不是B构造函数构造出来的
// 成哥:看A对象的原型链上有没有B的原型
//A instanceof B  

person instanceof Person  --> true
person instanceof Object  --> true  // 原型链顶端有Object
obj instanceof Person --> false  // 这俩没关系

数组和对象的类型都是Object

image-20221005165924255

// 判断数据的正确类型
var arr = [] || {};
var obj = {};

方法一:判断数组和对象的构造器

数组

image-20221005170239406

对象

image-20221005170321746

方法二: instanceof

image-20221005170429299

方法三:toString方法

// 调用this方法就是返回对应的类型,比如number调用toString返回[object,Number],对象数组返回结果与之类似

0bject.prototype.toString.call([]);  // 用call来执行 把this变成数组  所以数组就会替换this的位置  就会识别数组来返回结果
0bject.prototype.toString = function ( ) {
	// 这个this 谁调用的就指向谁
    // 识别this
    // 返回相应的结果
}
obj.toString();

根据返回的结果就能知道数据类型

295)]

对象

[外链图片转存中…(img-hUbHzVvO-1664961393296)]

方法二: instanceof

[外链图片转存中…(img-Z1IsvpV3-1664961393296)]

方法三:toString方法

// 调用this方法就是返回对应的类型,比如number调用toString返回[object,Number],对象数组返回结果与之类似

0bject.prototype.toString.call([]);  // 用call来执行 把this变成数组  所以数组就会替换this的位置  就会识别数组来返回结果
0bject.prototype.toString = function ( ) {
	// 这个this 谁调用的就指向谁
    // 识别this
    // 返回相应的结果
}
obj.toString();

根据返回的结果就能知道数据类型

image-20221005171143451

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好好学习_fighting

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值