前言
在学习JS原型、原型链和继承之前,我们必须先弄懂三个W,也就是我们常说的**“学习三问”**
学习三问:
1.它是什么?(What)
2.为什么用它?(Why)
3.什么时候用它?(When)
带着这三个问题去思考下面将要所学的知识,相信你一定会明白今后所学的每个知识点!!
友情提醒:学会某个知识点后一定要反复多敲几遍相关知识的代码,看懂和敲懂真的是两回事!
正文
1.原型prototype
(1)原型的定义:每个函数都有一个属性——prototype,在默认情况下,prototype的值就是一个普通的object对象(属性的集合),它有一个默认叫做constructor的属性,而constructor是用来指向这个函数本身(可以理解为函数的来源)。
**(2)原型的使用:**当一个函数被用作构造函数来创建实例时,这个函数的prototype属性值会被作为原型赋值给所有对象实例(也就是设置 实例的__proto__
属性),也就是说,所有实例的原型引用的是函数的prototype属性
注意:
1.prototype是函数(构造函数)的属性
2.__proto__是对象的属性
Person.prototype.name = "man";//在Person构造函数的原型上创建一个name属性并赋值
Person.prototype.say = function(){//在Person构造函数的原型上创建一个say方法
console.log("hello");
}
function Person(){}//创建一个构造函数
var person = new Person();//创建一个实例对象=>设置实例对象的__proto__属性(实例对象的原型链也就产生了)
console.log(person.name);// man
person.say();// hello
(3)consturctor 构造函数
**定义:**此属性只有原型对象才有,它默认指回prototype属性所在的构造函数
2.隐式原型 __proto__
定义:所有对象上都有的一个属性,叫做隐式原型,__proto__
,它指向创建该对象的构造函数的原型(prototype),即fn._proto_=== Fn.prototype
用法:
-
当访问一个对象的成员是,如果该对象中存在这个属性,直接使用
-
如果该属性不存在对象中,沿着该对象的隐式原型去查询
var obj = {
a:1,
b:2
}
obj.proto.c = 123;//往obj隐式原型直接添加c属性并赋值
console.log(obj.c)//123
注意:
1. 每个构造函数原型的隐式原型都指向Object.prototype,但是Object.prototype是
一个特例——它的__proto__指向的是null
,切记切记!!!(null其实就是JS给的一个出口值)
2.Function.__proto__指向自身Function.prototype,因为上文提到所有构造函数都是由大的Function创建的,既然Function是函数,当然指向的是其本身了
下面我将上文总结一张图,便于知识的整体梳理:(图片来源于掘金网技术社区)
f:代表自定义函数
3.原型链
定义:原型链即是隐式原型。
为什么说原型链就是隐式原型,相信看完上图结构你已经有所明白了!
因为每个对象和原型都有隐式原型,对象的隐式原型指向创建该对象的构造函数的原型对象,而父的原型又指向父的父,这种原型层层连接起来的就构成了原型链。
扩展知识:
-
JavaScript中非常重要的两条链
-
原型链的查找属性是从下往上的过程,作用域链的查找是从上往下的过程
-
作用域链中找不到出现报错,原型链找不到不会报错,出现undefined
4.原型的应用
**1.基础方法:**w3c不推荐直接使用系统属性
2.将伪数组转换为真数组
○Array.isArray(伪数组)
○ Array.prototype.slice.call(伪数组)
**3.**判断一个数组是不是真数组的常用方法