01.原型
1.函数的prototype属性
*每个函数都有一个prototype属性,它默认指向一个object空对象(原型对象)
*原型对象中有一个属性constructor,它指向函数对象
2.给原型对象添加属性(一般是方法)
*作用:函数的所有实例对象自动拥有原型中的属性(方法)
实现代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<script>
console.log(Date.prototype, typeof Date.prototype)//包含的属性给创建的实例来使用
function Fun () {
}
console.log(Fun.prototype) //默认指向一个object空对象(没有我们的属性)
//向原型中添加属性(一般是方法)===>实例对象可以访问
Fun.prototype.test = function () {
console.log('test()')
}
console.log(Fun.prototype)
console.log(Date.prototype.constructor === Date) //true
console.log(Fun.prototype.constructor === Fun) //true
var fun = new Fun()//创建实例
fun.test()//调用test
script>
body>
html>
02.显示原型与隐式原型
1.每个函数都有一个prototype,就是显示原型(属性)
2.每个实例对象都有一个__proto__,就是隐式原型(属性)
3.对象的隐式原型的值为其对应构造函数的显示原型的值
总结:
*函数的prototype属性:在定义函数时自动添加的,默认是一个空的object对象 this.prototype = {}
*对象的__proto__属性:创建对象时自动添加的,默认为构造函数的prototype属性值 this.__proto = Fn.prototype
*可以直接操作显示原型不能直接操作隐式原型(es6之前)
实现代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<script>
//定义构造函数
function Fn() { //内部语句:this.prototype = {}
}
// 1.每个函数都有一个prototype,就是显示原型(属性),默认指向一个空的Object对象
console.log(Fn.prototype)
// 2.每个实例对象都有一个__proto__,就是隐式原型(属性)
//创建实例对象
var fn = new Fn() //内部语句:this.__proto = Fn.prototype
console.log(fn.__proto__)
// 3.对象的隐式原型的值为其对应构造函数的显示原型的值
console.log(fn.__proto__ === Fn.prototype) //true
//给原型添加方法
Fn.prototype.test = function() {
console.log('test()')
}
//通过实例调用原型的方法
fn.test()
script>
body>
html>
03.原型链
1.原型链
*访问一个对象的属性时
*先在自身属性中查找,找到返回
*如果没有,再沿着__proto__这条链向上查找,找到返回
*如果最终没有找到,返回undefined
*别名:实质上是隐式原型链
*作用:查找对象的属性(方法) (一级一级往上查找)
2.构造函数/原型/实例对象的关系
3.构造函数/原型/实例对象的关系2原型链的补充:
1.函数的显示原型指向的对象,默认是空的Object实例对象(但Object不满足,Object.prototype.proto = null)
2.Function是它自身的实例,所有函数都是Function的实例(包含Function): Funtion = new Function()
3.Object 的原型对象是原型链尽头
实现代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<script>
// console.log(Object)
// console.log(Object.prototype)
console.log(Object.prototype.__proto__) //null
function Fn() { //重要!内部语句:this.prototype = {}
this.test1 = function () {
console.log('test1()')
}
}
console.log(Fn.prototype) //注意这里,默认指向一个Object空对象(也是Object实例对象) 实例对象__proto__的值=构造函数Object的prototype的值
Fn.prototype.test2 = function () {
console.log('test2()')
}
var fn = new Fn() //重要!内部语句:this.__proto = Fn.prototype
fn.test1()
fn.test2()
fn.toString() //定义在Object原型对象中的方法
console.log(fn.toString())
// fn.test3()
console.log(fn.test3) //undefined
// 原型链的补充
// 1.函数的显示原型指向的对象,默认是空的Object实例对象(但Object不满足,Object.prototype.__proto__ = null)
console.log(Fn.prototype instanceof Object) //true Fn.prototype是不是Object实例,后面有instanceof的讲解
console.log(Object.prototype instanceof Object) //false
console.log(Function.prototype instanceof Object) //true
// 2.Function是它自身的实例,所有函数都是Function的实例(包含Function)
console.log(Function.__proto__ === Function.prototype) //true
// 3.Object 的原型对象是原型链尽头
console.log(Object.prototype.__proto__) //null
script>
body>
html>
构造函数/原型/实例对象的关系图:
构造函数/原型/实例对象的关系图2:
*Funcion Foo(){} 就是var Foo = new Function() 所以函数也是一个实例对象,包含prototype和__proto__两个属性.
*实例对象的隐式原型 = 构造函数的显示原型 然而这里,构造函数的隐式原型和显示原型指向同一个对象,说明它是自己创建自己 Function = new Function() //自己创建的 Function.proto = Function.prototype.
*所有函数的隐式原型都应相等(都是new Function()产生的).
*Object create by function.
*函数对象的显示原型指向对象默认是Object空实例对象(由new Object()创建的实例),但Object不满足.
*Object原型对象是原型链尽头
1.读取对象的属性值: 会自动到原型链中查找
2.设置对象的属性值: 不会查找原型链,如果当前对象中没有次属性,直接添加此属性并设置其值
3.方法一般定义在原型中,属性一般通过构造函数定义在对象本身上
实现代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<script>
function Fn() {
}
Fn.prototype.a = 'xxx'
var fn1 = new Fn()
console.log(fn1.a) //xxx
var fn2 = new Fn()
fn2.a = 'yyy'
console.log(fn1.a,fn2.a,fn2) //xxx yyy
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.setName = function(name) {
this.name = name
}
var p1 = new Person('yang',24)
p1.setName('yue')
console.log(p1) //name:'yue',age:24
var p2 = new Person('qing',24)
p2.setName('ming')
console.log(p2) //name:'ming',age:24
console.log(p1.__proto__ === p2.__proto__) //true
script>
body>
html>
05.探索instanceof
案例1:
A instanceof B就是:A是不是B的实例
B函数的显示原型对象(B.prototype)是A.__proto__这条链上的某一个 就返回true,A是B的实例.如下图所示:
B.prototype与A.__proto__相交于一点,则A是B的实例.以下图来讲解
所以f1 (A)是Object(B)的一个实例.
案例2:
完整图部分:
(1).Object(A) instanceof Function(B),图解如下:
(2).Object(A) instanceof Object(B),图解如下:
(3).Function(A) instanceof Function(B),图解如下:
(4).Function(A) instanceof Object(B),图解如下:
(5).Object(A) instanceof Foo(B),图解如下:
06.面试题(画出原型链图)
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<script>
// 测试题1 画图
function A () {
}
A.prototype.n = 1
var b = new A()
A.prototype = { //原A.prototype属性是指向一个默认Object实例对象,现在指向一个新的对象{n=2,m=3}
n: 2,
m: 3
}
var c = new A()
console.log(b.n, b.m, c.n, c.m)// 1 undefined 2 3
// 测试题2(参照原型链图)
var F = function(){}
Object.prototype.a = function(){
console.log('a()')
}
Function.prototype.b = function(){
console.log('b()')
}
var f = new F()
f.a()
f.b() //不能执行
F.a()
F.b()
script>
body>
html>