原型
- 每一个函数都有一个属于自己的原型
-
作用: 我们会在原型内部放一些公共的方法, 目的不是为了让构造函数去使用, 而是为了让实例化对象去使用
const arr = new Array() const obj = new Object()找到数组构造函数的原型
const arr = new Array() console.log(arr.__proto__) console.log(Array.prototype)找到对象构造函数的原型
console.log(Object.prototype) -
任何一个数组的构造函数 都是 Array
-
任何一个对象的构造函数 都是 Object
-
任何一个函数的构造函数 都是 Function
-
万物皆对象
- 对象:
-
含义1: 一种数据格式 {key: value, key2: value2}
-
含义2: 某一类事务的实例 (某一类内容中的 真实个体)
const arr = [1, 2, 3] const arr1 = [1, 2, 3, 4] 这个 arr1 就是Array这一类内容中的某一个 真实个体, 数组也可以算作一个对象(Array 这一类事务中的一个个体) const fn = () => {console.log(1)} 函数也是一个对象(属于 Function 这一类事务中的一个个体)
-
原型链
- 查找对象的某一个属性:
-
先在对象内部开始查找, 找到直接使用, 然后停止查找
-
如果没有找到, 会找对象的 obj.proto, 如果找到直接使用, 然后停止查找
-
如果这里没找到, 会继续去对象的 proto 查找, 找到直接使用, 然后停止查找
-
如果还是没找到, 会继续向上查找 ...
-
直到找到顶层作用对象 Object.prototype, 找到就是用, 找不到 undefined
function Person (name) { this.name = name } Person.prototype.sayHi = function () { console.log(100) } const p = new Person('abc')
-
- 问题1: p 的 proto 指向谁?
-
p 是 Person 的实例化对象
-
proto 指向自身构造函数的原型
-
p.__proto === Person.prototype
-
-
问题2: Person 的 proto 指向谁?
- Person 是构造函数, 本质上函数
- 只要是一个函数, 他就是 Function 的实例
- Person.proto 指向了 他的构造函数的原型, 构造函数是 Function, 那么构造函数的 原型 Function.prototype
- Person.proto === Function.prototype
-
问题3: Person.prototype 的 proto 指向谁?
- Person.prototype 其实就是 构造函数 Person 的原型对象, 本质上就是对象
- 只要是一个 对象, 他就是 Object 的实例
- Person.prototype.proto 指向了 他的构造函数的原型, 构造函数 Object, 那么构造函数的原型 Object.prototype
- 问题4: Function 的 proto 指向谁?
- Function 是构造函数, 本质上就是一个函数
- 只要是一个函数, 他就是 Function 的实例
- Function.proto 指向了 他的构造函数的原型, 构造函数 Function, 那么 构造函数的原型 Function.prototype
- Function.proto === Function.prototype
- 问题5: Function.prototype 的 proto 指向了谁?
- Function.prototype 其实就是 构造函数 Function 的原型对象, 本质上是对象
- 只要是一个对象, 他就是 Object 的实例
- Function.prototype.proto 指向了 他的构造函数的原型, 构造函数 Object, 那么构造函数的原型 Object.prototype
- Function.prototype.proto === Object.prototype
- 问题6: Object 的 proto 指向了谁?
- Object 是一个构造函数, 本质上还是一个函数
- 只要是一个函数, 那么他的构造函数 就是 Function
- Object.proto 指向了他的构造函数的原型, 他的构造函数是 Function, 那么构造函数的原型 Function.prototype
- Object.proto === Function.prototype
- 问题7: Object.prototype 的 proto 指向了谁?
-
Object.prototype 是构造函数 Object 的原型对象, 本质上就是一个对象
-
但是重点: Object.prototype 是 JS 顶层的对象
-
Object.prototype.proto === null
console.log('1.', p.__proto__ === Person.prototype) // true console.log('2.', Person.__proto__ === Function.prototype) // true console.log('3.', Person.prototype.__proto__ === Object.prototype) // true console.log('4.', Function.__proto__ === Function.prototype) // true console.log('5.', Function.prototype.__proto__ === Object.prototype) // true console.log('6.', Object.__proto__ === Function.prototype) // true console.log('7.', Object.prototype.__proto__) // null
-
判断数据类型
-
-
typeof 判断基本数据类型
console.log(typeof('123')) console.log(typeof(123)) console.log(typeof(true))
-
-
- constructor 可以判断当前数据的构造函数是谁
-
问题1: 能够判断引用数据类型
- 但是! 这个属性其实就是对象内的一个属性
- 我们可以拿到这个对象, 然后修改他的属性值
-
问题2: 不能判断 undefined 和 null
const arr = [1, 2, 3] Array.prototype.constructor = { a: 1 } console.log(Array.prototype.constructor) // {a: 1} console.log(arr.__proto__.constructor === Array) // false console.log(undefined.constructor) // undefined 内部没有 constructor 所以我么不能这样去判断
-
-
instanceof 可以判断左边的构造函数是否等于右边的构造函数
-
语法: 检测的数据 instanceof 构造函数
-
问题: 不能判断 undefined 和 null
const arr = [1, 2, 3] console.log(arr instanceof Array) // true console.log(arr instanceof Function) // false console.log(undefined instanceof Array) // false
-
-
4.Object.prototype.toString.call(要判断的数据结构)
-
Object 这个构造函数的原型内部有一个toString的方法
-
这个方法能够帮我们将数据结构转为字符串的形式 '[object 数据结构]'
-
我们在使用的时候 如果需要判断其他数据类型, 需要使用 .call这个方法改变内部 this 指向
-
这个方法任何数据类型都能准确判断
const obj = { a: 1, b: 2 } console.log(Object.prototype.toString.call(obj)) // [object Object] console.log(Object.prototype.toString.call(undefined)) // [object Undefined]
-