爬虫&逆向--Day25&Day26--原型链补环境

一、文件描述符

属性描述符有两种主要类型:数据描述符存取描述符。你不能同时使用两者。

1.1.、数据描述符 (Data Descriptor)

描述一个具有值的属性。

  • value:该属性对应的值。默认为 undefined

  • writable:布尔值,表示属性的值(value)是否可以被改变(例如通过赋值运算符)。默认为 false

  • configurable:布尔值,表示该属性的描述符能否被改变,以及该属性能否从对象上被删除。默认为 false

  • enumerable:布尔值,表示该属性是否可枚举(例如是否会出现在 for...in 循环或 Object.keys() 中)。默认为 false

    let student01 = {
        name: "yuan",
        age: 18,
        height: 180
    }
    
    // (1) 对象属性的基础操作
    
    console.log(student01)              // { name: 'yuan', age: 18, height: 180 }
    console.log(student01.name)         // yuan
    student01.age = 19
    console.log(student01.age)          // 19
    student01.weight = "70kg"
    console.log(student01.weight)       // 70kg
    
    // (2) enumerable:是否可迭代  便利,循环 默认是true
    Object.defineProperty(student01,"weight",{
        enumerable:false   // 意思就是,我在便利这个对象student01的时候,这个属性weight的key不会被打印出来
    })
    
    for (const student01Key in student01) {
        console.log(student01Key)     // name  age  height
    }
    
    /*
    // (3) configurable:是否可配置  默认是true  是可以配置的
    Object.defineProperty(student01,"weight",{
        enumerable:true,
        configurable:false    //不可以配置  所以下面就不可以在进行Object.defineProperty在进行配置了,在配置就会报错误
    })
    
    //因为上面configurable:false  不可配置,所以这里在配置就会报错误
    Object.defineProperty(student01,"weight",{
        enumerable:true,
        configurable:false
    })
    */
    
    
    // (4) writable:value值是否可以改变
    Object.defineProperty(student01,"weight",{
        enumerable:true,
        configurable:true,
        writable:true,    // 是否可写  student01.weight = "60kg"
    })
    
    student01.weight = "60kg"       // 对这个weight写入
    console.log(student01.height)   // 180
    console.log(student01.weight)   // 60kg  读取这个weight 这个属性的值  因为不存在所以是undefined
    
    
    
    // (5) value:属性对应的值
    Object.defineProperty(student01,"weight",{
        enumerable:true,
        configurable:true,
        writable:true,
        value:"60kg"    // 给一个默认值
    })
    
    student01.weight = "70kg"
    console.log(student01.height)       // 180
    console.log(student01.weight)       // 70kg
    
    
    //(6) get方法和set方法
    weight_val = "60kg"
    Object.defineProperty(student01,"weight",{
        enumerable:true,
        configurable:true,
        get:function (){
            console.log("student01正在获取属性weight")
            return weight_val
        },
        set:function (val){
            console.log("student01.weight正在赋值")
            // this.weight = val //  无限递归
            weight_val =val
        },
        // value:""// value不能和get、set混搭
    })
    
    console.log(student01.weight)
    student01.weight = "80kg"
    console.log(student01.weight)
    /*
    student01正在获取属性weight
    60kg
    student01.weight正在赋值
    student01正在获取属性weight
    80kg
     */

二、原型链

在JavaScript中,每个对象都有一个特殊的属性叫做"prototype"(原型)。它是一个指向另一个对象的引用,在对象之间实现继承关系。

当你访问一个对象的属性或方法时,如果该对象自身没有这个属性或方法,JavaScript引擎会自动去该对象的原型中查找。如果原型中也没有找到,那么会继续在原型的原型中查找,直到找到该属性或方法或者到达原型链的末尾。

在JavaScript中,原型的概念与面向对象编程的继承紧密相关。你可以通过原型来共享属性和方法,从而实现对象之间的继承关系。

案例1:

function Person(name) {
  this.name = name;
}
​
Person.prototype.greet = function() {
  console.log("Hello, my name is " + this.name);
};
​
var person = new Person("John");
person.greet(); // 输出:Hello, my name is John
  1. prototype(原型对象)就是一个容器. {},存放公共的方法或者属性给对象使用.

  2. 对象可以直接访问原型对象中的方法和属性.

  3. 原型对象类似Python的类对象(fn.prototype)

原型对象和函数之间的关系.

  • 每个函数都会有一个prototype属性,指向原型对象.

  • 每个原型对象都会有一个constructor属性,指向函数.

  • 总结:每个函数与原型对象之间的关系是互相引用.

img

对象和原型对象和函数之间的关系

  • 函数创建对象var o = new Fn();

  • 对象通过__proto__属性,指向原型对象.

  • 对象可以直接调用原型对象中所有的属性和方法.

  • 对象可以通过原型对象中的constructor属性知道构造函数

  • 总结: 原型对象就是一个容器,帮助函数存放公共方法,以及给函数new出来的对象提供公共方法使用.

img

function Dog(name, age) {
    this.name = name;//面试题:构造函数中的this指向谁? 答:指向new创建的对象
    this.age = age;
    this.sleep = function () {
        console.log("sleeping")
    }

}

// Dog("rain",12) // 普通函数
//构造函数
let alex = new Dog("alex", 36);   // 使用new来创建对象
let eric = new Dog("eric", 35);   // 使用new来创建对象

// (1) 函数对象通过prototype容器设置公共属性和方法
Dog.prototype.eat = function (food) {
    console.log(this.name +"吃"+ food);
}

alex.eat("吃骨头")      // alex吃吃骨头
eric.eat("吃肉")       // eric吃吃肉

// (2) 对象通过`__proto__`属性,指向原型对象
console.log(alex.__proto__)                     // { eat: [Function (anonymous)] }
console.log(alex.__proto__.constructor.name)    // Dog
console.log(alex.__proto__.constructor)         // [Function: Dog]

// 看看能不能理解
console.log(alex.__proto__ === Dog.prototype)   //true
console.log(Dog.prototype)                      // { eat: [Function (anonymous)] }

alex.age = 100
console.log(alex.age)   // 100 先查找自己的空间,找不到,去原型中找
console.log(eric.age)   // 35

// 猜一猜1
Dog.prototype.sleep =function (){
    console.log("prototype sleeping")
}

alex.sleep()    // sleeping

// 猜一猜2
let zhangSan = new Dog("张三", 35);
Dog.prototype = {
    fly:function (){
        console.log("flying...")
    }
}
// let zhangSan = new Dog("张三", 35);
// zhangSan.fly()
zhangSan.eat("辣条")  // 张三吃辣条
// 类的声明
function Person(name, age,height) {
    // 不是每个人都一样的需要放到这里
    this.name = name
    this.age = age
    /* this.eat = function (){
         console.log(this.name + " 正在吃饭")
     }*/

    this.height = height
}

// 如果所有的实例化对象都有eat方法和legs_num属性,并且eat方法的逻辑都是一样的,legs_num的值都是一样
// 那么我们就可以把这些共有的不改变的这些属性和方法都放到Person类的prototype空间中去
//类方法
Person.prototype.eat = function () {
    console.log(this.name + " is eating")
}
// 类属性
Person.prototype.legs_num = 2


// 类的实例化一个对象
let p1 = new Person("yuan", 18,175)
// 实例化的属性调用
// console.log(p1.name)
let p2 = new Person("rain", 19,180)
// console.log(p2.name)
// p1.eat()
// p2.eat()
// console.log(p1.legs_num)
// console.log(p2.legs_num)

// console.log(p1.height)
// console.log(p2.height)

// 函数对象(类对象)调用prototype获取它的原型对象   通过函数找这个函数的原型对象就用prototype
console.log(Person.prototype)       // { eat: [Function (anonymous)], legs_num: 2 }
ptt = Person.prototype   // 给原型对象赋一个变量ptt  这个ptt就是一个原型对象
// 原型对象通过constructor获取该原型对象的函数对象(类对象)
console.log(ptt.constructor)       // [Function: Person]

// `__proto__`
// 实例对象通过__proto__直接找到原型对象
console.log(p1.__proto__)                   // { eat: [Function (anonymous)], legs_num: 2 }
console.log(p1.__proto__=== Person.prototype)
console.log(p1.__proto__.constructor)       // [Function: Person]
console.log(p1.__proto__.constructor === p2.__proto__.constructor)

 


 

 

 

posted @ 2025-09-24 15:20  L遇上J  阅读(63)  评论(0)    收藏  举报