JavaScript全解析之面向对象——原型和原型链
类语法的书写
●在 ES6 的语法标准中, 管构造函数不叫做构造函数了, 叫做 类
●语法:
class 类名 {constructor () {
// 书写属性
}
书写原型上的方法
方法名 () {}
}
// ES6 类的语法
class Person {
// 等价于 ES5 的构造函数体
constructor(name) {
this.name = name
}
// 直接书写原型上的方法
sayHi() { console.log('你好 世界') }
play() { console.log('play game') }
}
const p = new Person('Jack')
console.log(p)
p.sayHi()
p.play()
// 此时 Person 已经不是函数了, 是一个 类
// 不能当做函数来调用
Person('Rose')
原型和原型链
●我们之前学过构造函数了,也知道了原型对象和对象原型
●那么问题出现了,我们说构造函数的 prototype 是一个对象
●又说了每一个对象都天生自带一个 proto 属性
●那么 构造函数的 prototype 里面的 proto 属性又指向哪里呢?
万物皆对象
●在 JS 内, 任何一个数据类型其实都是对象
○函数也是一个对象, 数组也是一个对象, 正则也是一个对象, ...
○是对象, 就可以存储 键值对
●以函数为例
○当你书写完毕一个函数的时候
○此时函数数据类型出现了, 同时该函数名也是一个对象数据类型
<script>
function fn() {
console.log('今天真好');
}
fn.a = 100
console.log(fn);
/*
ƒ fn() {
console.log('今天真好');
}
*/
console.dir(fn)
/*
ƒ fn()
a: 100
arguments: null
caller: null
length: 0
name: "fn"
prototype: {constructor: ƒ}
[[FunctionLocation]]:
[[Prototype]]: ƒ ()
[[Scopes]]: Scopes[1]
*/
</script>
●以数组为例
<script>
let arr = [100, 200, 300]
arr.b = 200
console.log(arr); // [100, 200, 300, b: 200]
console.dir(arr);
/*
Array(3)
0: 100
1: 200
2: 300
b: 200
length: 3
[[Prototype]]: Array(0)
*/
</script>
●通过上面的示例说明在js中一切都可以看做对象
●在上面的示例中新添加的是不会在代码中体现的,不过是确实存在的
●这就是说明在内存中是有两部分组成的 一部分是本身的,一部分是对象形式的
一个对象所属的构造函数
●每一个对象都有一个自己所属的构造函数
●比如: 数组
// 数组本身也是一个对象
var arr = []
var arr2 = new Array()
以上两种方式都是创造一个数组
●我们就说数组所属的构造函数就是 Array
比如: 函数
// 函数本身也是一个对象
var fn = function () {}
var fun = new Function()
●以上两种方式都是创造一个函数
●我们就说函数所属的构造函数就是 Function
constructor 构造函数
●原型对象prototype 里面也有一个成员叫做 constructor
●也就是说constructor是原型对象上的一个属性
●这个属性的作用就是指向当前这个对象所属的构造函数
<script>
function Person(name) {
this.name = name
}
let p1 = new Person('张三')
console.log(p1);
console.log(p1.constructor === Person);
console.log(p1.__proto__.constructor === Person);
console.log(Person.prototype.constructor === Person);
</script>
原型链详解
●我们想要清楚的弄明白什么是原型链就需要清楚的知道以下几个问题
●通过下面的一个构造函数来详细的说明
<script>
function Person(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
}
Person.prototype.sayHi = function() {
console.log('hello world')
}
const p1 = new Person('Jack', 18, '男')
console.log(p1)
</script>
●概念:
○1、 每一个函数天生自带一个属性叫做 prototype, 是一个对象数据类型
○2、每一个对象天生自带一个属性叫做 proto, 指向所属构造函数的 prototype
○3、任何一个对象, 如果没有准确的构造函数, 那么看做是 Object 的实例。只要是一个单纯的对象数据类型, 都是内置构造函数 Object 的实例
1、p1 身上的 proto 是谁
●因为 p1 是 Person 的实例
●根据概念1 得到, p1.proto 指向所属构造函数的 prototype
console.log(p1.__proto__ === Person.prototype)
2、Person 的 proto 是谁
●Person 是一个构造函数, 同时也是一个函数, 同时也是一个对象
●只要是对象就会有 proto 属性
●JS 内有一个内置构造函数叫做 Function, 只要是函数, 就看做 Function 的实例
●任何一个函数数据类型所属的构造函数都是 Function
●Person 看做是 Function 的实例
●Person 所属的构造函数就是 Function
●Person.proto 指向 Function.prototype
console.log(Person.__proto__ === Function.prototype)
3、Person.prototype 的 proto 是谁
●Person.prototype 是函数天生自带的一个对象数据类型
●只要是对象就会有 proto 属性
●JS 内有一个内置构造函数叫做 Object, 只要是单纯的对象, 都是 Object 的实例
●Person.prototype 是一个天生的对象数据类型, 并且是一个单纯的对象数据类型
●把 Person.prototype 看做是 Object 的实例
●Person.prototype 的 proto 就是 Object.prototype
console.log(Person.prototype.__proto__ === Object.prototype)
4、Function 的 proto 是谁
●Function 是一个构造函数, 同时也是一个函数, 同时也是一个对象
●只要是对象就会有 proto 属性
●JS 内有一个内置构造函数叫做 Function, 只要是函数就是 Function 的实例
●Function 自己本身是一个内置构造函数, 本身也是一个函数
●Function 自己是自己的实例, 自己是自己的构造函数
●在 JS 内管 Function 叫做顶级函数
●Function.proto 就是 Function.prototype
console.log(Function.__proto__ === Function.prototype)
5、Function.prototype 的 proto 是谁
●Function.prototype 是函数天生自带的一个对象数据类型
●只要是对象就会有 proto 属性
●Function.prototype 是一个天生的对象数据类型, 并且是一个单纯的对象数据类型
●把 Function.prototype 看做是 Object 的实例
●Function.prototype 的 proto 就是 Object.prototype
console.log(Function.prototype.__proto__ === Object.prototype)
6、Object 的 proto 是谁
●Object 是一个构造函数, 同时也是一个函数, 同时也是一个对象
●只要是对象就会有 proto 属性
●Object 也是一个函数, 只要是函数就是 Function 的实例
●Object 这个内置函数所属的构造函数依旧是 Function
●Object.proto 就是 Function.prototype
console.log(Object.__proto__ === Function.prototype)
7、Object.prototype 的 proto 是谁
●Object.prototype 是函数天生自带的一个对象数据类型
●只要是对象就会有 proto 属性
●在 JS 内, Object 是顶级对象, Object.prototype 是顶级原型
●Object.prototype 是唯一一个没有 proto 的对象数据类型
●Object.prototype 的 proto 是 null
console.log(Object.prototype.__proto__)
原型链
●概念:用 proto 串联起来的对象链状结构
●作用:为了对象访问机制服务(当你访问一个对象成员的时候, 为你提供一些服务)
●注意:只是 proto 串联起来的对象链状结构, 和原型对象 prototype 没有关系
原型链的访问原则
●我们之前说过,访问一个对象的成员的时候,自己没有就会去 proto 中找
●接下来就是,如果 proto 里面没有就再去 proto 里面找
●一直找到顶级圆形对象 Object.prototype 里面都没有,那么就会返回 undefiend
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
//创建一个构造函数
function Person() {
this.name = 'Jack'
this.age = 18
this.gender = '男'
}
//构造函数的原型对象上添加一个a方法
Person.prototype.a = function() {
console.log('Person.prototype')
}
//内置对象的原型对象上添加一个b方法
Object.prototype.b = function() {
console.log('Object.prototype')
}
//内置构造函数的原型对象上添加一个c方法
Function.prototype.c = function() {
console.log('Function.prototype')
}
// 创建一个 Person 的实例
const p = new Person()
console.log(p)
//访问实例上的name属性
console.log(p.name)
//调用实例上的a方法
p.a()
//调用实例上的b方法
p.b()
console.log(p.c)
//调用C方法
Person.c()
//调用b方法
Person.b()
</script>
</body>
</html>
猜你喜欢LIKE
相关推荐HOT
更多>>servlet底层原理是什么?
1、ServletAPI核心类与接口2、Servlet类处理请求的流程创建servlet类的步骤:创建一个命名为TestServlet继承javax.servlet.http.HttpServlet类详情>>
2023-05-30 10:41:22多线程的优势与劣势分别是什么?
多线程是指在同一个程序中,同时运行多个线程,每个线程都可以独立执行不同的任务,相互之间不会干扰。多线程的优势和劣势如下:优势:提高程序...详情>>
2023-05-30 10:32:12设计模式之生产者与消费者的代码实现
本文主要讲述生产者和消费者模式,文中会使用通俗易懂的案例,使你更好地学习本章知识点并理解原理,做到有道无术。什么是生产者和消费者模式生...详情>>
2023-05-30 10:25:46从零开始学Java之interface接口
一.接口简介简介Java中的接口(interface)类似于是一种特殊的抽象类,它也是众多抽象方法的集合。接口的定义方式、组成部分都与抽象类相似,却比...详情>>
2023-05-29 11:26:17热门推荐
如何进行mysql数据备份?
沸什么是servlet的生命周期?servlet请求处理流程是怎样的?
热servlet底层原理是什么?
热怎样编写java程序?
新多线程的优势与劣势分别是什么?
ssm框架的作用与原理是什么?
设计模式之生产者与消费者的代码实现
接口和抽象类有什么区别?4个方面对比
从零开始学Java之interface接口
从零开始学Java之Java中的内部类是怎么回事?
一分钟带你了解MySQL——基础与介绍
在java中,super关键字怎样使用
什么是事件流以及事件流的传播机制 ?
弹性盒有哪些属性是在父元素身上?