javascript原型链污染漏洞
基础知识
对prototype
和__proto__
的区分
个人对两个概念的理解
prototype
存在的意义?
疑问来自于:prototype
是每个函数的模板,储存了函数的属性和方法,那为什么我们不可以直接在函数中加上方法属性,为什么非要如下对构造函数进行书写呢:1
2
3
4
5
6
7
8
9function Person(name){
this.name = name;
}
Person.prototype.sayhello = function(){console.log("hello");};
const Bob = new Person("Bob");
const Alice = new Person("Alice");
Bob.sayhello();
//此时Bob和Alice都会继承父类Person的prototype里的方法以及自带的name属性。解答:
若是按照如下书写,不使用prototype
:1
2
3
4
5
6
7
8
9
10function Person(name){
this.name = name;
this.sayhello = function(){
console.log("hello");
}
}
const BOb = new Person("Bob");
const Alice = new Person("Alice");
Bob.sayhello();
console.log(Alice.sayhello === Bob.syahello);//输出false,因为它们为独立函数那么每次实例化一个新的对象,都会在该对象内部实例化一个新的方法,会导致内存大大浪费,如上述代码。
所以,我们会使用prototype
属性给原型构造函数设定属性和方法,以便在重复实例化对象的时候出现不必要的内存浪费,并且还可以继承原型构造函数的方法。
如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26// 父类(人类)
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`我是 ${this.name}`);
};
// 子类(学生类)
function Student(name, grade) {
// 继承父类属性
Person.call(this, name);
this.grade = grade;
}
// 继承父类方法(关键!)
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
// 添加子类专属方法
Student.prototype.study = function() {
console.log(`${this.name} 在学习`);
};
const alice = new Student("Alice", 90);
alice.sayHello(); // 继承自 Person 的方法
alice.study(); // 子类专属方法这里就可以看出构造函数的方法属性一条龙继承下来。
对于
__proto__
该属性是每个对象的固有属性!(非标准,ES6 后被
Object.getPrototypeOf
取代)
而刚刚说的prototype
只有构造函数才具有该属性。
每个对象的__proto__
属性即指向了其原型构造函数的prototype
属性,即其中的属性和方法。
使用如下代码:1
console.log(Bob.__proto__);
因为
Bob.__proto__
会指向Person.prototype
,所以输出的仅为:1
2
3
4{
sayHello: function() { console.log("hello"); },
constructor: Person
}不会包含
this.name = name
:this.name
是实例属性,直接存储在Bob
和Alice
对象中,不会出现在原型链。
区分
属性 | 类型 | 存在对象 | 用途 | 访问方式 |
---|---|---|---|---|
prototype |
函数属性 | 仅函数对象 | 定义新对象的原型 | Function.prototype |
__proto__ |
对象属性 | 所有对象 | 指向当前对象的原型,即当前对象原型的prototype |
Object.__proto__ (不推荐) |
如下代码即可很快区分:
1 | function Foo() {} |
- 关键点
foo.__proto__ === Foo.prototype
(新对象的__proto__
指向构造函数的prototype
)。Foo.prototype.__proto__ === Object.prototype
(函数的prototype
默认继承自Object.prototype
)。
- 特别注意:
prototype
是函数用来定义新对象原型的“模板”。不是对象的上级原型!
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Dedsec的博客!