当前位置:网站首页>Detailed explanation of js prototype
Detailed explanation of js prototype
2022-07-31 07:08:00 【Fire orchid】
js中的原型毫无疑问一个难点,学习如果不深入很容易就晕了!
任何一个js知识点,比如事件流,闭包,继承等,都有许许多多的说法,对于这些知识点我们都应该先熟练的使用,然后自己整理一套属于自己的理解说辞,才不会忘
原型(对象属性)
Javascript规定,每一个函数都有一个prototype对象属性,指向另一个对象(原型链上面的).
prototype(对象属性)的所有属性和方法,都会被构造函数的实例继承.这意味着,我们可以把那些不变(公用)的属性和方法,直接定义在prototype对象属性上.
prototype就是调用构造函数所创建的那个实例对象的原型(proto).
prototype可以让所有对象实例共享它所包含的属性和方法.也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息添加到原型中.
原型链 (JS原型与原型链继承)
实例对象与原型之间的连接,叫做原型链.proto( 隐式连接 )
JS在创建对象的时候,都有一个叫做proto的内置属性,用于指向创建它的函数对象的原型对象prototype.
内部原型(proto)和构造器的原型(prototype)
1、每个对象都有一个proto属性,原型链上的对象正是依靠这个属性连结在一起
2、作为一个对象,当你访问其中的一个属性或方法的时候,如果这个对象中没有这个 方法或属性,那么Javascript引擎将会访问这个对象的proto属性所指向上一个对 象,并在那个对象中查找指定的方法或属性,如果不能找到,那就会继续通过那个对象 的proto属性指向的对象进行向上查找,直到这个链表结束.
实际开发中,有这样一种写法,面向对象,这种写法就是通过构造函数以及原型来运用的(混合模式开发面向对象)
每一个函数都有一个原型属性prototype(对象属性),里面放置的是共有、公有的属性或者方法.(一般情况属性是私有的).注意,只有函数才有prototyoe属性,
function Person() {
}
var p = new Person()
console.log(Person.prototype); // Object{}
console.log(p.prototype); //undefined
这个例子可以发现,函数是存在prototype属性的
任何对象都是默认存在构造器的,此时我们的Person()只是普通函数,它其实是js内置方法Function()构造出来的,而p此时是Person() new出来的,只有new 过了,才叫构造函数
浅谈constructor
在 Javascript 语言中,constructor 属性是专门为 function 而设计的,它存在于每一个 function 的prototype 属性中.这个 constructor 保存了指向 function 的一个引用.
上代码更容易理解
function Person() {
}
var p = new Person()
console.log(Person.prototype); // Object{}
console.log(p.prototype); // undifined
console.log(p.constructor); //function Person(){}
此处的p是通过 Person函数构造出来的,所以p的constructor属性指向Person
console.log(Person.constructor); //function Function(){}
之前提过,每个函数其实是通过new Function()构造的
console.log({}.constructor); // function Object(){}
每个对象都是通过new Object()构造的
console.log(Object.constructor); // function Function() {}
Object也是一个函数,它是Function()构造的
console.log([].constructor); //function Array(){}
我想大家此时对于prototype属性有了一定的了解
console.log(Object.constructor); // function Function() {}
可能大家对于这个有些不理解,毕竟我们实际开发中哪见过这玩意
console.log(Function instanceof Object); // true
console.log(Object instanceof Function); // true
这样大家是不是就明白了呢 函数是对象构造的 对象也是函数构造的,俩者即是函数也是对象,所以为什么构造函数它是一个函数却返回一个对象,俩者是互相继承的关系
var o1 = new f1();
typeof o1 //"object"
重点讲解一下原型prototype的用法,最主要的方法就是将属性暴露成公用的,上代码
function Person(name,age){
this.name = name;
this.age = age;
this.sayHello = function(){
console.log(this.name + "say hello");
}
}
var girl = new Person("bella",23);
var boy = new Person("alex",23);
console.log(girl.name); //bella
console.log(boy.name); //alex
console.log(girl.sayHello === boy.sayHello); //false
再看下面的代码
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.sayHello=function(){
console.log(this.name + "say hello");
}
var girl = new Person("bella",23);
var boy = new Person("alex",23);
console.log(girl.name); //bella
console.log(boy.name); //alex
console.log(girl.sayHello === boy.sayHello); //true
我们给函数Person的原型中声明了sayHello方法,当我们的构造实例对象去访问的时候访问的方法是同一个,这就是prototype原型最大的作用,共享属性和方法
那么prototype与proto有什么关系,先看这么一串代码
var obj = {}
此处等价于 var obj = new Object()
console.log(obj.__proto__ === Object.prototype)//true
JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做 __proto__ 的内置属性,用于指向创建它的构造函数的原型对象.
根据前面的例子我们很清楚,obj是通过new Object 构造出来的一个对象,那我们Object的原型对象就是Object.prototype,在Object下面构造出来的所有对象,都有一个__proto__ 指向它的原型,我们称这个为原型链
var obj = []
console.log(obj.__proto__ === Array.prototype)//true
这个也是一样的道理
此处要理解,就是原型对象是谁构造的,是谁构造的我们看构造器
console.log(Array.prototype.constructor)//Array{}
原型对象肯定是它本身构造的,Then look at the previous constructor code
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.sayHello=function(){
console.log(this.name + "say hello");
}
var girl = new Person("bella",23);
var boy = new Person("alex",23);
console.log(Person.prototype.constructor); //Person
console.log(girl.__proto__==Person.prototype); //true
console.log(girl.constructor==Person); //true
See if it's very simple now 注意这里是两个下划线__proto__ 叫 杠杠proto杠杠
Next give a string of code
function Person(){
}
var person1=new Person()
快速回答
1.person1.__proto__==
2.person1.constructor==
3.Person.__proto__==
4.Person.prototype.constructor==
5.person1.prototype.constructor==
6.Person.prototype==
You can test whether the input answer is printed or nottrue if you play soon,It means that you have understood it thoroughly
Next, I will find a few questions to analyze together,深入了解
function A(){
}
function B(a){
this.a = a;
}
function C(a){
if(a){
this.a = a;
}
}
A.prototype.a = 1;
B.prototype.a = 1;
C.prototype.a = 1;
console.log(new A().a); //1
console.log(new B().a);//undefined
console.log(new C(2).a);//2
我们先观察第一个
new A() 很明显它是A()构造的实例对象,在下面A函数prototype共享了一个属性a=1,那么实例对象也可以通过这个属性访问到他的值==1
第一个比较简单,我们看第二个
第二个其实是个坑,首先B()函数它声明的时候设置了一个参数,注意里面的方法this,此时this指向的是window,我们都知道,然而在构造函数之后this指向了new B(),然而此时B 没有传入参数,也就是说此时的参数a==undefined,
因此new B()下的属性a==this.a==undefined (不知道这么说能不能理解 ̄□ ̄||)
如果我们给B 传入一个数(可以是a,但a一定要先声明)
console.log(new B(3).a); //3
console.log(new B(5).a); //5
这样应该就好理解了,总不能我们自己设置的属性还覆盖不来爸爸给你的属性吧
第三个很好理解,从第二个的角度分析,如果传入参数,输出参数,如果没有 输出1
这道题没什么拐弯,比较简单,我们再看一题
function Fun(){
var getName = function(){
console.log(1);
}
return this;
}
Fun.getName = function(){
console.log(2);
}
Fun.prototype.getName = function(){
console.log(3);
}
var getName = function(){
console.log(4);
}
function getName(){
console.log(5);
}
Fun().getName(); //4
getName(); //4
new Fun().getName();//3
new new Fun().getName();//3
做题一定要一步步来,先看第一个 Fun().getName();
很明显此时是Fun()调用getName(),我们看看Fun(),注意,函数的返回值永远是return,此处return返回了this,在函数中这里的this指向window,也就是说第一步Fun( )返回的是window,转换一下就是window.getName(),
我们在什么找一下全局的getName,最终输出4
第二个其实很简单,我感觉就是来迷惑我们的,前面省略了window,很明显还是4
第三个也太简单了,只要你理解了我上面写的内容,一看就知道输出3
第四个,两个new? 不要慌 我们来分析一下
new后面跟的肯定是函数,用来构造实例对象,所以new Fun()这是不能拆的,
很明显此时new Fun()是一个构造函数,虽然称之为函数,但其实它是一个对象,因为函数是方法,而方法是不能调用属性的,但是对象可以,既然是对象,何来new 构造呢,所以此处分析可以得到new Fun ().getName才是一体连着的,
那很明显就是原型下的方法咯,所以输出3
边栏推荐
猜你喜欢
随机推荐
gstreamer的caps event和new_segment event
Oracle入门 02 - IT软硬件平台及操作系统介绍
选择排序法
MySQL官网8.0.17 安装教程(适合离线安装)
银河麒麟服务器v10 sp2安装oracle19c
What is float?What is document flow?Several ways and principles of clearing floats?What is BFC, how to trigger BFC, the role of BFC
Koa框架的基本使用
记录一下,今天开始刷剑指offer
Skywalking安装部署
Oracle入门 11 - Linux 开关机及系统进程命令
(border-box)盒子模型w3c、IE的区别
全网首发!ADK To Win11PE(1)中文+包
对van-notice-bar组件定义内容进行设置
快速傅里叶变换(FFT)
批量免费文字翻译
DHCP原理与配置
js原型详解
Debian 10 dhcp 服务配置
讲解实例+详细介绍@Resource与@Autowired注解的区别(全网最全)
磁盘和储存管理









