对象、原型、原型链

对象 原型 原型链

对象

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries

对象的方法

1 Object.assign(target,source1,source2) 对象合并,合并到target对象上
2 Object.create(proto,null) 已现有对象为原型,创建一个新对象
3 Object.defineProperties(obj,{property1:{},property2:{},…}) 在对象上新增新属性或修改现有属性,返回此对象
属性配置的描述
  configurable 该属性是否可以被删除且是否修改配置项 默认false
  enumerable 该属性是否可被枚举 默认false
  value 该属性值
  writable 该属性是否可以重新被复制 默认false

  get 该属性的getter函数,函数返回值用作属性的值
  set 该属性的setter函数,只有一个参数,属性的新值
4 Object.definedProperty(obj,property,{}) 在对象上定义一个新属性或者修改现有属性,返回此对象
5 Object.entries() 返回一个包含[key,value]对象所有的属性名和属性值 [[key,value],[key,value]]
6 Object.fromEntries() 将键值对列表转化为对象 如:map对象

 const object1 = { a: 1, b: 2, c: 3 };
 const object2 = Object.fromEntries(
   Object.entries(object1).map(([key, val]) => [key, val * 2]),
 );

 console.log(object2);
// { a: 2, b: 4, c: 6 }

原型 原型链

原型的理解

在这里插入图片描述

原型链的理解
对象的封装
生成实例对象的原始模式
通过字面量生成
let cat1 = {};
cat1.name = 'zs';
cat1.color='黑色';

let cat2 = {};
cat1.name = 'ls';
cat1.color='白色';

缺点:1 生成多个实例,写起来麻烦;2 实例与原型之间,没有任何办法看出联系

原始模式改进

写一个函数,解决代码重复问题

 function Cat(name,color){
   return {
     name:name,
     color:color
   }
 }

 let cat1 = Cat('zs',黑色)
 let cat2 = Cat('ls',白色)

缺点: 应然看不出cat1与cat2 之间的联系,不能反映他们是同一个原型对象的实例

构造函数模式
// 原型对象
 function Cat(name,color){
  this.name = name;
  this.color = color;
 }
// 生成实例对象
let cat1 = new Cat('zs',黑色)
let cat2 = new Cat('ls',白色)

cat1和cat2会自动含有一个constructor属性,指向他们的构造函数 
cat1.constructor = Cat // true
cat2.constructor = Cat // true

instanceof验证原型对象和实例之间的关系  
cat1 instanceof Cat // true
cat2 instanceof Cat // true

构造函数的问题

浪费内存

 function Cat(name,color){
  this.name = name;
  this.color = color;
  this.type = '猫科动物';
  this.eat = function(){alert('吃老鼠')}
 }

let cat1 = new Cat('zs',黑色)
let cat2 = new Cat('ls',白色)
cat1.type // 猫科动物  
cat1.eat() // 吃老鼠

缺点: 每一个实例对象,type属性和eat()方法都是一模一样的内容,每一次生成一个实例,都必须为重复的内容,导致多占内存
cat1.eat === cat2.eat //false 指向不同的内存地址

prototype模式

每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法都会被构造函数的实例继承

 function Cat(name,color){
  this.name = name;
  this.color = color;
 }
 Cat.prototype.type = '猫科动物';
 Cat.prototype.eat = function(){
   alert('吃老鼠')
 }

let cat1 = new Cat('zs',黑色)
let cat2 = new Cat('ls',白色)
cat1.type // 猫科动物  
cat1.eat() // 吃老鼠

cat1.eat === cat1.eat // true
对象的继承

猫来继承动物

 function Animal(){
  this.species = '动物'
 }
 function Cat(name,color){
  this.name = name;
  this.color = color;
 }
构造函数绑定

使用call或apply方法,把父对象的构造函数绑定到子对象上

 function Cat(name,color){
  Animal.apply(this,arguments);
  this.name = name;
  this.color = color;
 }
 let cat1 = new Cat('zs','黑色')
 cat1.species // 动物
prototype模式
Cat.prototype = new Animal();
<!-- 每个prototype对象都有一个constructor属性,指向他的构造函数,所以需要让Cat.prototype.constructor重新指向他自己的构造函数 -->
Cat.prototype.constructor = Cat;
直接继承prototype

第三种方法是第二种方法的改进,由于Animal对象中,不变的属性都可以直接写到 Animal.prototype中,可以直接让Cat()跳过Animal(),直接继承Animal.prototype

 重写Animal构造函数
 function Animal(){};
 Animal.prototype.species = '动物';

 继承
 Cat.prototype = Animal.prototype;
 Cat.prototype.constructor = Cat;

优点:效率比较高,不用执行和建立Animal实例,省内存
缺点:Cat.prototype和Animal.prototype指向同一个对象,则对Cat.prototype的修改会有反应到Animal.prototype

 Animal.prototype.constructor === Cat  // true
利用空对象作为中介

由于“直接继承”有上述缺点,则利用一个空对象作为中介

let F = function(){};
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;
F是空对象,所及几乎不占用内存

new Fun() 发生了什么?

1 在内存中创建一个新对象
2 让this指向这个空对象
3 执行构造函数中的代码,给这个新对象添加属性和方法
4 返回这个新对象

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值