day19 原型和继承

原型

prototype

概述:是属于函数的一个空间,是一个对象。(构造函数属于函数所以也具备),prototype属性称为显示原型。

因为prototype作为一个对象,所以也具有属性和方法,主要是方法,所以prototype属性上一般存放对应的方法。

构造函数的prototype

复制代码
function Person(){
}
console.log(Person.prototype);
//获取当前的构造函数
console.log(Person.prototype.constructor);
//将函数存储在原型上
Person.prototype.sayHello = ()=>{
console.log(this);
}
//新建对象
var person = new Person()
var person1 = new Person()
console.log(person == person1);//false
//person.sayHello ===> Person.prototype.sayHello
//对于prototype上存储的内容 通过实例对象.属性名访问
console.log(person.sayHello == person1.sayHello);//true
///对于prototype上存储的内容 通过实例对象.属性名访问
console.log(person.constructor);
复制代码

构造函数的prototype是一个对象,里面有个属性constructor指向当前的构造函数

实例对象访问prototype上的内容可以通过实例对象,属性名访问

一般将对应的函数存储在对应的prototype上(这个函数只会声明一次)。将属性放在构造函数里面

prototype里面声明的函数的this指向当前调用的实例对象

--proto--

概述:--proto--称为隐式原型,它是属于对象的一个空间,每个对象都存在这个空间,对应的实例也是一个对象,所以也具有这个空间。这个空间指向对应的构造函数的prototype

__proto__ 指向对应的构造函数的prototype
构造函数也是一个对象 它的 __proto__指向对应的父类的构造函数的prototype
Object的 __proto__ 指向null

复制代码
var obj = new Object()
//每个对象都存在的一个空间 它指向对应的构造函数的prototype
console.log(obj.__proto__);
//对象的__proto__指向对应的构造函数的prototype
console.log(obj.__proto__ == Object.prototype);
function Person(){
}
var person = new Person()
console.log(person.__proto__ == Person.prototype);
// Person.prototype.sayHello = ()=>{
// }
person.__proto__.sayHello = ()=>{
console.log('hello');
}
person.sayHello()
复制代码

原型链:对象在__proto__上找属性的链式结构

对象在原型上找属性的过程: 

  1. 先找自己的 __proto__ (对应的构造函数的prototype),
  2. 再找对应的自身构造函数的原型的 __proto__ 找到父类构造函数的原型,再找对应的父类的原型的 __proto__ ,直到找到object为止
  3. Object的原型的 __proto__ (null)上还找不到返回undefined
复制代码
Object.prototype.hello = '你好'
class Person{
constructor(){
this.name = '张三'
}
}
Person.prototype.sex = '女'
Person.prototype.username = 'rose'
//对象赋值 有就重新赋值 没有就添加属性赋值
Person.hi = '你好吗'
var person = new Person()
person.age =
'
109'
class Son extends Person{
constructor(){
super()
this.age = '李四'
}
}
Son.prototype.sex = '男'
//实例化对象
var son = new Son()
console.log(son.age);//李四
console.log(son.name);//张三
console.log(son.username);//rose
console.log(son.sex);//
console.log(son.hello);//你好
console.log(son.hi);//undefined
复制代码

注意:对象赋值不属于原型链,对象赋值的操作只是找到这个属性然后重新赋值,如果没有找到这个属性,则添加这个属性然后进行赋值

总结
构造函数的原型prototype
实例对象的原型 __proto__
实例对象的 __proto__ 指向构造函数的prototype
原型链通过对应的对象的 __proto__ 去找对应的属性 直到找到Object为止
原型一般上面写函数,可以保证函数只声明一次。对应的属性写在构造函数内。
原型上的方法/属性。通过实例对象.属性名直接访问(平常通过对象去点的方法都称为原型方法)
在对应的原型上的函数里面的this指向当前调用的实例对象

能够通过原型来实现数组的高阶函数(forEach,map,reduce...)

面向对象的三大特性:封装、继承、多态(重写 子类重写父类方法)

继承:子类继承父类的属性和方法(非私有属性和方法  非静态方法)

继承的实现 1.使用extends关键词实现继承(es6新增 类的继承)

                    2.原型链继承 (覆盖之前原型上的所有方法 显示的时候不会显示继承来的属性 (在原型上重复出现一样的属性))核心: 在子类的原型上创建父类的对象                 

                    3.对象冒充 (会显示继承的属性 不能继承原型上的方法)核心 在子类中调用父类的构造函数 更改this指向

                     4.组合继承 (使用原型链继承和对象冒充结合)

                     5.组合寄生继承 (对象冒充 + 原型链继承(创建一个原型对象放在原型链上))

复制代码
// es6新增类的继承 extends关键词实现
class Person{
constructor(){
this.name = 'jack'
}
}
class Son extends Person{
constructor(age){
super()
this.age = age
}
}
var son = new Son(18)
console.log(`son`, son);


//原型继承
// 将要继承的类放在继承的子类的原型上
//原型链会覆盖原本原型上的私有的方法及属性
Son.prototype = new Person()

//对象冒充

function Son(age){
//改this指向 执行父类的构造函数
Person.call(this)
this.age = age
}

// 组合继承 原型链继承加对象冒充
function Person(){
this.name = 'jack'
}
Person.prototype.say = ()=>{
console.log(`hello`);
}
function Son(age){
//改this指向 执行父类的构造函数
Person.call(this)
this.age = age
}
//原型链继承
Son.prototype = new Person()
var son = new Son(18)
console.log(`son`, son);
son.say()

//组合寄生继承
function Person(){
this.name = 'jack'
}
Person.prototype.say = ()=>{
console.log(`hello`);
}
function Son(age){
//改this指向 执行父类的构造函数
Person.call(this)
this.age = age
}
//寄生
Son.prototype = Object.create(Person.prototype)
var son = new Son(18)
console.log(`son`, son);
复制代码

ES6的模块化
模块的思想,将对应的功能代码封装为一个模块(js代码 css代码 html代码)。
想要使用别人就导入,想要给别人用就导出。复用。
模块化的常用的模式
amd (在对应的加载之前导入)
cmd (在用的时候导入)
comment.js (基于amd和cmd之上)
es6的模块化的关键词
import 导入
export 导出

第一种 export default (只能声明一次)

复制代码
// //默认导出只有一个 如果使用export default 导出的可以使用对应的一个名字来接
export default {
obj,
str,
say
}
//接收
import obj from './test.js'
console.log(obj) //{obj,str,say}
复制代码

第二种

复制代码
//如果直接使用的对应的export 导出那么必须通过{键}来接
export const obj = {
name:
'
jack',
age:18
}
//如果导出的是值类型 一定要写变量名
export const str =
"
你好世界"
export const say = ()=>{
console.log('hello world');
}
//接收
import {obj,str,say} from './test.js'
复制代码

第三种

复制代码
import使用
const name = 'tom'
//第三种导出
export {
//只能写变量
name
}
//接收
import {name} from './test.js'
import 名字 from '地址'
复制代码

 

posted @   xiaomingff  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示