爬虫学习(五)

目录

1.js函数

1.1 Object.getPrototypeOf

1.2 Object.setPrototypeOf

1.3 Object.getOwnPropertyDescriptor

1.4 Object.getOwnPropertyNames

1.5 Object.getOwnPropertySymbols

1.6 Object.keys 

2.js知识点

2.1 >>>

2.2 >>

2.3 特殊函数调用方式


1.js函数

1.1 Object.getPrototypeOf

方法在 JavaScript 中用于获取指定对象的原型对象,即对象链中的下一个链接。原型对象是对象继承属性和方法的来源。

下面是一个使用 `Object.getPrototypeOf` 方法的例子:

// 构造函数
function Animal(name) {
  this.name = name;
}

// 添加一个方法到 Animal 原型上
Animal.prototype.speak = function() {
  console.log(this.name + ' makes a sound.');
};

// 使用构造函数创建一个实例
const animal = new Animal('Generic animal');

// 获取 animal 实例的原型对象
const proto = Object.getPrototypeOf(animal);

// 由于 Animal.prototype 被设置为 animal 的原型,proto 将指向 Animal.prototype
console.log(proto === Animal.prototype); // 输出: true

// 调用通过原型继承的 speak 方法
proto.speak.call(animal); // 输出: Generic animal makes a sound.

// 创建另一个对象,使用 Object.create 方法设置其原型为 animal 实例
const anotherAnimal = Object.create(animal);

// 此时,anotherAnimal 的原型是 animal 实例
const anotherProto = Object.getPrototypeOf(anotherAnimal);
console.log(anotherProto === animal); // 输出: true

// 由于 anotherAnimal 是以 animal 为原型创建的,它不会继承 Animal.prototype 上的方法
anotherProto.speak.call(anotherAnimal); // 输出: undefined makes a sound.

在这个例子中,我们首先定义了一个 `Animal` 构造函数,并为其原型添加了一个 `speak` 方法。然后,我们使用 `new` 关键字创建了一个 `animal` 实例。

通过 `Object.getPrototypeOf` 方法,我们获取了 `animal` 实例的原型对象,它指向 `Animal.prototype`。因此,当我们调用 `proto.speak.call(animal)` 时,它能够正确地输出 `animal` 实例的名字和它发出的声音。

1.2 Object.setPrototypeOf

在 JavaScript 中用于设置一个对象的原型(即内部的 `[[Prototype]]` 属性)。这个方法通常用于改变对象的继承链,或者将一个对象的原型设置为 `null` 来防止进一步的原型继承。

下面是一个使用 `Object.setPrototypeOf` 方法的例子:

// 构造函数
function Animal(name) {
  this.name = name;
}

// 添加一个方法到 Animal 原型上
Animal.prototype.speak = function() {
  console.log(this.name + ' makes a sound.');
};

// 使用构造函数创建一个实例
const animal = new Animal('Generic animal');

// 创建另一个构造函数
function Vehicle(make, model) {
  this.make = make;
  this.model = model;
}

// 添加一个方法到 Vehicle 原型上
Vehicle.prototype.describe = function() {
  console.log('This is a ' + this.make + ' ' + this.model + ' vehicle.');
};

// 使用构造函数创建一个 Vehicle 实例
const car = new Vehicle('Toyota', 'Corolla');

// 现在,我们将 car 实例的原型设置为 animal 实例
// 这意味着 car 将继承 animal 实例的所有属性和方法
Object.setPrototypeOf(car, animal);

// 验证原型链是否已改变
console.log(Object.getPrototypeOf(car) === animal); // 输出: true

// 由于 car 的原型现在是 animal,它继承了 speak 方法
car.speak(); // 输出: Generic animal makes a sound.

// 为了演示,我们也可以将 car 的原型设置为 null,这样它就不再有原型
Object.setPrototypeOf(car, null);

// 再次验证原型链
console.log(Object.getPrototypeOf(car) === null); // 输出: true

// 现在 car 没有原型,因此不能访问 speak 方法
car.speak(); // 输出: TypeError: car.speak is not a function

在这个例子中,我们首先定义了两个构造函数 `Animal` 和 `Vehicle`,并分别为它们的原型添加了方法 `speak` 和 `describe`。然后,我们分别使用这两个构造函数创建了 `animal` 和 `car` 实例。

接下来,我们使用 `Object.setPrototypeOf` 方法将 `car` 实例的原型设置为 `animal` 实例。这意味着 `car` 现在继承了 `animal` 实例的所有属性和方法。我们通过调用 `car.speak()` 来验证这一点,它输出了 `animal` 实例的名字和声音。

最后,我们再次使用 `Object.setPrototypeOf` 方法将 `car` 的原型设置为 `null`,这意味着 `car` 将不再继承任何属性和方法。当我们尝试调用 `car.speak()` 时,由于 `car` 没有 `speak` 方法,因此抛出了一个类型错误。

1.3 Object.getOwnPropertyDescriptor

`Object.getOwnPropertyDescriptor` 方法在 JavaScript 中用于获取指定对象上给定属性的描述信息。描述信息是一个包含属性的各种元数据的对象,例如属性是否可枚举、是否可写、默认值以及 getter 和 setter 函数等。

这个方法对于深入了解对象属性的具体行为和特征非常有用,尤其是在调试或者需要精确控制对象属性时。

下面是一个使用 `Object.getOwnPropertyDescriptor` 方法的例子:

// 创建一个对象,并定义一个属性
const myObject = {
  myProperty: 'Hello, World!'
};

// 定义一个 getter 和一个 setter 函数
const getter = function () {
  return this.myProperty + ' (accessed via getter)';
};

const setter = function (newValue) {
  this.myProperty = newValue + ' (updated via setter)';
};

// 使用 Object.defineProperty 为对象添加一个带有 getter 和 setter 的属性
Object.defineProperty(myObject, 'accessorProperty', {
  get: getter,
  set: setter,
  enumerable: true,
  configurable: true
});

// 使用 Object.getOwnPropertyDescriptor 获取属性描述信息
const descriptor = Object.getOwnPropertyDescriptor(myObject, 'accessorProperty');

// 打印属性描述信息
console.log(descriptor);
// 输出:
// {
//   value: 'Hello, World! (accessed via getter)',
//   writable: false,
//   enumerable: true,
//   configurable: true,
//   get: [Function: getter],
//   set: [Function: setter]
// }

// 直接访问属性值
console.log(myObject.accessorProperty); // 输出: 'Hello, World! (accessed via getter)'

// 修改属性值
myObject.accessorProperty = 'Goodbye, World!';
console.log(myObject.accessorProperty); // 输出: 'Goodbye, World! (updated via setter)'

在这个例子中,我们首先创建了一个对象 `myObject` 并给它定义了一个普通的属性 `myProperty`。接着,我们定义了一个 getter 函数和一个 setter 函数,并将它们与 `Object.defineProperty` 方法一起使用,为 `myObject` 添加了一个带有访问器(accessor)的属性 `accessorProperty`。

使用 `Object.getOwnPropertyDescriptor` 方法,我们获取了 `accessorProperty` 的描述信息,并打印出来。描述信息对象包含了属性的值、是否可写、是否可枚举、是否可配置以及 getter 和 setter 函数的引用。

然后,我们通过直接访问 `accessorProperty` 来触发 getter 函数,并打印出它的返回值。之后,我们尝试修改 `accessorProperty` 的值,这将触发 setter 函数,并将修改后的值打印出来。

1.4 Object.getOwnPropertyNames

`Object.getOwnPropertyNames` 方法在 JavaScript 中用于获取一个对象的所有可枚举的自有属性的名称,包括那些不可枚举的属性。这个方法返回一个字符串数组,数组中的每个元素都是对象的一个属性名。

这个方法对于理解对象的内部属性非常有用,尤其是当你想要获取对象所有的属性,包括那些可能在常规枚举中被忽略的属性时。

下面是一个使用 `Object.getOwnPropertyNames` 方法的例子:

// 定义一个对象
const myObject = {
  enumerableProperty: 'I am enumerable',
  nonEnumerableProperty: 'I am not enumerable'
};

// 添加一个不可枚举的属性
Object.defineProperty(myObject, 'anotherNonEnumerableProperty', {
  value: 'Another non-enumerable property',
  enumerable: false
});

// 使用 Object.keys 获取对象的键(只能获取可枚举的键)
const keys = Object.keys(myObject);
console.log(keys); // 输出: ["enumerableProperty"]

// 使用 Object.getOwnPropertyNames 获取对象的所有自有属性名称
const allPropertyNames = Object.getOwnPropertyNames(myObject);
console.log(allPropertyNames); // 输出: ["enumerableProperty", "nonEnumerableProperty", "anotherNonEnumerableProperty"]

在这个例子中,我们首先定义了一个对象 `myObject`,它包含一个可枚举属性 `enumerableProperty` 和一个不可枚举属性 `nonEnumerableProperty`。然后,我们使用 `Object.defineProperty` 方法添加了另一个不可枚举属性 `anotherNonEnumerableProperty`。

当我们使用 `Object.keys` 方法时,它只返回了可枚举的属性 `enumerableProperty`。然而,当我们使用 `Object.getOwnPropertyNames` 方法时,它返回了所有的自有属性名称,包括那些不可枚举的属性 `nonEnumerableProperty` 和 `anotherNonEnumerableProperty`。

1.5 Object.getOwnPropertySymbols

在 JavaScript 中用于获取一个对象的所有自有符号属性(Symbol properties)。符号属性是一种特殊的属性,它通过 `Symbol` 函数创建,具有唯一性,即使两个不同的 `Symbol` 看起来可能相同,它们在技术上也是不同的。

这个方法对于处理那些希望避免属性名冲突的高级用例非常有用,因为 `Symbol` 值是唯一的,不会与其他属性名或 `Symbol` 值冲突。

下面是一个使用 `Object.getOwnPropertySymbols` 方法的例子:

// 创建一个对象
const myObject = {};

// 定义两个符号属性并添加到对象中
const sym1 = Symbol('uniqueDescription1');
const sym2 = Symbol('uniqueDescription2');

myObject[sym1] = 'This is a symbol property with description 1';
myObject[sym2] = 'This is another symbol property with description 2';

// 使用 Object.getOwnPropertyNames 获取对象的所有自有字符串属性名称
const stringPropertyNames = Object.getOwnPropertyNames(myObject);
console.log(stringPropertyNames); // 输出: []

// 使用 Object.getOwnPropertySymbols 获取对象的所有自有符号属性
const symbolProperties = Object.getOwnPropertySymbols(myObject);
console.log(symbolProperties); // 输出: [Symbol(uniqueDescription1), Symbol(uniqueDescription2)]

// 打印符号属性的描述和值
symbolProperties.forEach(sym => {
  console.log(`Symbol description: ${sym.description}, Symbol value: ${myObject[sym]}`);
});
// 输出:
// Symbol description: uniqueDescription1, Symbol value: This is a symbol property with description 1
// Symbol description: uniqueDescription2, Symbol value: This is another symbol property with description 2

在这个例子中,我们首先创建了一个空对象 `myObject`,然后定义了两个具有不同描述的符号,并使用这些符号作为属性名将它们添加到 `myObject` 中。我们还为这些符号属性赋予了字符串值。

当我们使用 `Object.getOwnPropertyNames` 方法时,它没有返回任何属性名称,因为 `myObject` 中没有可枚举的字符串属性。然而,当我们使用 `Object.getOwnPropertySymbols` 方法时,它返回了一个包含所有自有符号属性的数组。

最后,我们遍历了符号属性数组,并打印了每个符号的描述和对应的值。这展示了如何访问和使用符号属性,尽管在大多数情况下,我们更倾向于使用 `Object.keys` 或 `Object.getOwnPropertyNames` 来处理常规属性。

1.6 Object.keys 

Object.keys 方法在 JavaScript 中用于获取一个对象自身的所有可枚举属性的键名(属性名),并以数组的形式返回。这个方法通常用于遍历对象的属性,尤其是当你需要对对象的属性进行操作时。

下面是一个使用 `Object.keys` 方法的例子:

// 创建一个对象,包含多个属性,其中一些属性是不可枚举的
const myObject = {
  enumerableProperty: 'This property is enumerable',
  nonEnumerableProperty: 'This property is not enumerable',
  anotherEnumerableProperty: 'Another enumerable property'
};

// 使用 Object.defineProperty 为对象添加一个不可枚举的属性
Object.defineProperty(myObject, 'anotherNonEnumerableProperty', {
  value: 'This is another non-enumerable property',
  writable: true,
  enumerable: false,
  configurable: true
});

// 使用 Object.keys 获取对象的可枚举属性键名
const keys = Object.keys(myObject);
console.log(keys); // 输出: ["enumerableProperty", "anotherEnumerableProperty"]

// 尝试使用 for...in 循环遍历对象的所有属性
for (const key in myObject) {
  console.log(key + ': ' + myObject[key]);
}
// 输出:
// enumerableProperty: This property is enumerable
// nonEnumerableProperty: This property is not enumerable
// anotherEnumerableProperty: Another enumerable property
// anotherNonEnumerableProperty: This is another non-enumerable property

// 说明:for...in 循环会枚举对象自身的属性以及其原型链上可枚举的属性

在这个例子中,我们首先创建了一个 `myObject` 对象,它包含一个可枚举属性 `enumerableProperty`,一个不可枚举属性 `nonEnumerableProperty`,以及一个通过 `Object.defineProperty` 添加的不可枚举属性 `anotherNonEnumerableProperty`。

当我们使用 `Object.keys` 方法时,它只返回了可枚举的属性键名,即 `enumerableProperty` 和 `anotherEnumerableProperty`。不可枚举的属性 `nonEnumerableProperty` 和 `anotherNonEnumerableProperty` 没有被包含在内。

随后,我们使用 `for...in` 循环遍历对象的所有属性,包括可枚举和不可枚举的属性。这是因为 `for...in` 循环不仅枚举对象自身的属性,还会枚举其原型链上可枚举的属性。

2.js知识点

2.1 >>>

在JavaScript中,三个大于号(>>>)是一种无符号右移位运算符。它将操作数的二进制表示向右移动 指定的位数,右侧用零填充,然后返回结果。

let num = 16 >>> 2;
console.log(num);

在这个例子中,16被右移两位,因此它的二进制表示变为了100(即4),然后它被转换为十进制并赋给 num变量。因此,这段代码将打印出4。 请注意,这个运算符与另一个右移位运算符(>>)不同,后者是有符号右移,它将在右侧使用符号位进行填充,这可能会导致负数的出现。

2.2 >>

在JavaScript中,双大于号(>>)是带符号的右位移运算符。这个运算符将一个数的二进制表示向右移 动指定的位数,并用符号位(即正负号位)填充左侧空缺的位数。例如,对于二进制数101101,右移两 位变为001011,因为符号位是0,所以结果是正数11。如果原数是负数,则填充左侧空缺位数的符号位 都是1,以保持负数的符号不变。 另外,双大于号(>>)也可用于将数字强制转换为32位有符号整数,因为JavaScript中的所有数字都是 以双精度浮点数的形式存储的。在进行位移运算之前,双大于号(>>)会将数字强制转换为32位有符号 整数。如果数字大于等于2的31次方,则结果为负数,否则为正数。

2.3 特殊函数调用方式

2.3.1

(0, a[i(_0x58e7("0x171"))])(u + f)

这里a[i(_0x58e7("0x171"))]是个混淆后的函数,这里实际上就是调用了这个函数,参数是u+f。

2.3.2

e.headers = e.headers || {}

这段代码是在JavaScript中常用的一种写法,它的作用是创建一个空的对象,如果e.headers对象已经存 在,则保留原有的对象;如果e.headers对象不存在,则将一个新的空对象赋值给它。

2.3.3

function s(n) {
var n = new z[M1](T1 + n + C1);
return (n = z[I][P1][A1](n)) ? z[g2](n[2]) : F
}

这段代码是一个JavaScript函数,它接受一个参数n,并对参数进行加密。具体来说,它将一个字符 串"T1 + n + C1"作为参数传递给z构造函数,创建一个新的z对象,并将其作为参数传递给z对象的P1方 法。然后将结果赋值给变量n,并检查变量n是否存在。如果n存在,则使用z对象的g2方法将n数组的第 二个元素解密为一个字符串,并返回该字符串。如果n不存在,则返回F。

2.3.4 

forEach(function(n) {
if (n == p)
return !B;
hasOwnProperty(n) && a['push'](t["params"][n])
})

这段代码是JavaScript函数的一部分,其中使用forEach循环来遍历一个由变量'n'表示的元素数组。循环 检查当前元素'n'是否等于某个值'p'。如果条件为真,则返回布尔值'B'的相反值。 如果条件为假,则循环通过使用'hasOwnProperty()'方法检查对象'a'是否有一个名为'n'的属性。如果该属 性存在,则从对象't'的'params'属性中检索相应的值,并使用'push()'方法将其添加到数组'a'中。

2.3.5

在 Node.js 环境中,可以使用 Buffer 对象的 toString 方法将字符串编码为 base64 格式,也可以 使用 Buffer 对象的 from 方法将 base64 格式的字符串解码为原始数据。

const str = 'hello world';
const base64Str = Buffer.from(str).toString('base64');
console.log(base64Str); // aGVsbG8gd29ybGQ=

2.3.6

将 base64 格式的字符串解码为原始数据。

const base64Str = 'aGVsbG8gd29ybGQ=';
const originalData = Buffer.from(base64Str, 'base64').toString();
console.log(originalData); // hello world

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值