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__上找属性的链式结构
对象在原型上找属性的过程:
- 先找自己的 __proto__ (对应的构造函数的prototype),
- 再找对应的自身构造函数的原型的 __proto__ 找到父类构造函数的原型,再找对应的父类的原型的 __proto__ ,直到找到object为止
- 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 '地址'
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现