对象、原型和继承

认识对象

对象的创建方法

1、

var obj={};

对象字面量/对象直接量(plain Object)


2、

构造函数:

1、系统自带的构造函数 Object()

var obj=new Object

2、自定义构造函数 当函数前面加上new时此函数就成了构造函数

​ 必须符合大驼峰式命名规则

​ 构造函数同样可以传参

function Person(){
    this.name='aaa';
    this.sex='bbb';
    this.age=66;
};
var person1=new Person();

构造函数内部原理

1、在函数体最前面隐式的加上var this={}

2、执行this.xxxx

3、在函数的最后隐式的加上return this;


对象的增删改查

1、增:对象名.属性名=值

var obj={
    name:abc,
    sex:male,
    age:20,
}
obj.height=170;

2、删:delete 对象名.属性名

var obj={
    name:abc,
    sex:male,
    age:20,
}
delete obj.name;

3、改:方法与增一样

4、查:对象名.属性名

var obj={
    name:abc,
    sex:male,
    age:20,
}
console.log(obj.name);

对象枚举(遍历)

1、for in 循环

var obj={
    name:'lihui',
    age:22,
    sex:'male',
}

for(var i in obj){
    console.log(obj[i]);
}

2、hasOwnProperty()

​ 此方法用于判断对象内属性是自己的属性还是原型的属性,返回值为布尔值

var obj={
    name:'lihui';
    age:22,
    sex:'male';
    __proto__:{
        lastName='shengpi',
    }
}

for(var i in obj){
    if(obj.hasOwnProperty(i)){
        console.log(obj[i]);
    }
}

3、in

​ 只能用于判断该属性能否被该对象所访问,能则返回true

var obj={
    name:'lihui';
    age:22,
    sex:'male';
    __proto__:{
        lastName='shengpi',
    }
}

console.log('name' in obj);

4、instanceof

//A instanceof B
//官方解释:A对象是否是B构造函数构造出来的
//实际:A对象的原型链上是否有B的原型

堆和栈

基本类型数据

number string boolean undefined null

引用类型数据

object array function

基本类型数据的变量名和值都存放于栈内存中

引用类型数据的变量名存放于栈内存中,真实值存放于堆内存中,栈内存中存放的只是一个指向堆内存内真实

包装类

基本类型数据没有属性也没有方法

例:当我们执行如下代码时 str本身是一个基本类型数据,它既没有属性也没有方法,当我们.length时,系统默认将字符串转换为对象,从而调用length属性;这个过程就是包装类;执行完毕后此过程会立即被删除。

这就造成了我们所看到的字符串类型数据能够直接调用length属性这一假象。

var str='abc'
console.log(str.length);
//new String('abc').length

练习

以下代码执行结果为 undefined

var str='abc';
str+=1var test=typeof(str);
if(test.length==6){
   test.sign=('typeof的返回结果可能为String')// new String('String').sign=xxxx       -->delete
}
console.log(test.sign);
//new String('String').sign

拷贝

拷贝:复制数据的值


深拷贝:复制者与被复制者互不影响

var a=3;
var b=a;
a=20;
console(b); 

此时b值依然为3,不随a的变化而变化


浅拷贝:复制者与被复制者相互影响

var obj={};
var c=obj;
obj.name='abc';
c.age=3;
console.log(obj);
console.log(c);

1547217170646

两者的值都改变了

深拷贝方法封装

function deepCopy(data){
	var newCopy=[];
    if(data.constractor.name==='Array'){
        for(var i=0;i<data.length;i++){
            newCopy.push(data[i]);
        }
        return newCopy;
    }else{
    var newCopy={};
        for(var i in data){
            newCopy[i]=data[i];
        }
        return newCopy;
    }
}

原型

原型定义

原型时function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。

原型中的属性不能通过他的后代修改和添加

//当一个对象通过构造函数Person被定义时 就产生了原型
//原型是构造函数Person下的一个对象 prototype={}
//我们可以人为给这个对象添加一些属性,而之后通过这个构造函数产生的对象都可以访问这个属性
Person.prototype.name='张旭';
function Person(){
    
}
var person=new Person();
var person1=new Person();

原型的用处

1、可以提取公有属性

原型中自带的属性

1、constructor属性

该属性会返回生成这个函数的构造器

我们可以手动修改这个属性的属性值 从而使其返回其他的构造函数

2、__ proto __ 属性:

这个属性指向的是原型对象 我们可以通过这个属性修改原型指向

原型链

如下代码所示,将对象son的原型设置为对象father,又将对象father的原型设置为对象test,这就构成了原型链;由此我们可以通过对象son访问以上两个对象的所有属性。

Test.prototype.sex='male';	
function Test(){
    
}
var test=new Test();

Father.prototype=test;
function Father(){
    this.name='aa';
}
var father=new Father;

Son.prototype=father;
function Son(){
    this.hobbit='smoke';
}
var son=new Son();

绝大多数对象都最终继承自Object.prototype

然而当使用Object.create()创建对象时就出现了例外

//var obj=Object.create(null);

obj1={
    name:'zhangxu',
    age:22,
	sex:'male',
}

var obj=Object.create(obj1);

注意:当使用该方法创建对象时()中只能写null或者原型,使用null所创建出来的对象是没有任何原型的,也就不继承于Object.prototype;即使我们人为的给其添加__ proto __属性,该属性也是不生效的。

undefined和null不能通过包装类转换成对象,因此也就不具有原型,更不可能继承于Object.prototype


原型中的方法

以toString()方法为例:Object.prototype下有toString()方法, Number.prototype,Stirng.prototype,Boolean.prototype,Array.prototype下都有toString()方法,不同原型中的toString()方法是不一样的,我们可以人为的对它进行删除或者重写,从而达到我们想要的效果。

var num=222;
//重写
Number.prototype.toString=function(){
    return '张旭傻逼';
}
console.log(num.toString());//输出结果为 张旭傻逼
//删除
delete Number.prototype.toString;

判断对象和数组的方法

1、constructor

var obj={};
var arr=[];

console.log(obj.constructor);
console.log(arr.constructor);

2、instanceof

var obj={};
var arr=[];

console.log(arr instanceof Array);
console.log(obj instanceof Array);

3、toString

var obj={};
var arr=[];

console.log(Object.prototype.toString.call(obj));
console.log(Object.prototype.toString.call(arr));

继承发展史

1、传统形式---->原型链

过多的继承了没用的属性

2、借用构造函数(call/apply) 严格意义上讲不是继承

不能继承借用构造函数的原型

每次构造函数都要多走一个函数

3、共享原型

Father.prototype.name='wo';
function Father(){
    
}
function Son(){
    
}
Son.prototype=Father.prototype
var son=new Son();

共享原型继承方法封装

Father.prototype.lastName='aaa';
function Father(){

}
function Son(){
    
}

function inherit(Target,Orgine){
    Target.prototype=Orgine.prototype;
}
inherit(Son,Father);

此时 我们就实现了将Son和Father的原型都指向了Father的原型,但是这个方法有一个弊端:

当我们改变Son的原型的时候 Father的原型也跟着改变了 ,这就引出了我们下面的:

4、圣杯模式

Father.prototype.lastName='aaa';
function Father(){

}
function Son(){
    
}
	
function F(){
    
}

function inherit(Target,Origin){
   F.prototype=Origin.prototype;
   Target.prototype=new F();
   Target.prototype.constructor=Target;
   Target.prototype.uber=Origin;
}
inherit(Son,Father);

此方法中可以看出 我们使用了一个第三方函数F

先将Father的原型赋给F,然后让Son继承于F,此时我们修改Son的原型时,F的原型会受到影响 但是不影响Father的原型

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值