JS逆向基础第一弹——变量声明、Object对象及静态方法

本文介绍了JavaScript中的变量声明,包括var、let和const的使用及作用域,强调了它们的区别,如var的变量提升、let的块级作用域以及const的不可修改性。此外,详细讲解了Object对象及其常用静态方法,如create、defineProperty、getPrototypeOf等,帮助理解JavaScript中的对象操作。
摘要由CSDN通过智能技术生成

1. JS 中的变量声明

1.1 var 的使用以及作用域

​ (1).作用域是指函数或变量的可供访问的范围。

​ (2). var可以定义全局变量和局部变量

​ (3). var的作用域主要和函数的定义有关

​ I.全局作用域

​ 如果是在任意函数的外部声明var变量,其作用域是全局的;

​ II.局部(函数)作用域

​ 如果是在函数内部声明var,其作用域是局部的,只能在函数内部被访问;

​ 对其他块定义没有作用域,比如if、for,这就会导致外部同名变量可以随意修改在if/for内定义的变量。

​ III. var 的声明与变量提升

​ 在使用变量前,需要先对变量进行声明,如果只声明、未赋值,则会初始化值为undefined。

​ var可以修改,也可以被重复声明。当对var 进行重复声明时,后面的变量可以覆盖前面的变量,相当于变量重置。

​ var的变量提升: JS引擎在预编译代码时,会优先获取所有被var声明的变量和函数,将它们放在代码的头部然后从上到下执行。

1.2 let 的使用以及作用域

​ (1).let允许声明一个作用域被限制在 块级中的变量、语句或者表达式。与 var 关键字不同的是, var声明的变量只能是全局或者整个函数块的。

​ (2).let声明的变量 只在它所处的代码块内有效,属于块级作用域。块是由 { } 界定的。

​ (3).let 可以被修改,但不能被重复声明。

注意:这里的重复声明是指let不允许在相同作用域内,重复声明同一个变量。

​ (4).let不存在变量提升

​ (5).暂存性死区

1.3 const 的使用以及作用域

​ (1). 像let声明一样,const 声明只能在声明它们的块级作用域中访问

​ (2). const 声明一个只读的常量,这意味着声明后的常量不能被修改并且不能被重复声明,这也意味着const声明时就必须初始化,不能等到之后赋值。

所以,当我们修饰的标识符不会被再次赋值时, 就可以使用const来保证数据的安全性。

1.4 总结

作用域:

​ var声明的是全局作用域或函数作用域;而let和 const 是块作用域。

声明初始化:

​ var和let在声明的时候可以不进行初始化;而 const 在声明的时候必须初始化。

修改与重复声明:

​ var在可以修改和重复声明;而let只能修改,不能在同一作用域下重复声明;const 声明常量不可修改也不可重复声明。

变量提升:

​ var声明的变量存在变量提升,即变量可以在声明之前调用,值为undefined;let和 const 不存在变量提升,即它们所声明的变量一定要在声明后使用,否则会报错。

暂存性死区:

​ var不存在暂时性死区;let和const存在暂时性死区,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

2. JS中的Object对象及静态方法

JavaScript中的对象其实就是一组数据和功能的集合。

通过new操作符后跟要创建的对象类型的名称来创建。

​ new:

​ 从指定模具中复刻出一个一模一样的空间,此空间与外界隔离,视为实例。

​ 由上可得new运算符就是进行创建空间与外界隔离后得到实例的一个过程。

//创建一个Object对象
var  o = new Object();

这里的Object相当于祖宗一样,创建Object的实例并没有什么用处。

特点:

每个Object类型的实例共有的属性和方法:

  • constructor: 保存着用于创建当前对象的函数。
  • hasOwnProperty:用于检测给定的属性在当前对象的实例中是否存在。
  • isPrototypeOf : 用于检查传入的对象是否是当前对象的原型
  • propertyIsEnumerble : 用于检查给定属性能否使用for-in来枚举
  • toLocaleString() : 返回对象的字符串表示。
  • toString() : 返回对象的字符串表示。
  • valueOf() : 返回对象的字符串,数值,或布尔表示。通常和toString() 返回的值相同。

JavaScript中几乎所有的事务都是对象,比如我们的函数。

​ Function

​ 在javascript中,函数(Function)是一段被封装好的代码,可以被反复使用(调用);

​ 函数可以是一个值、一个对象、一类数据,还可以是一个表达式,因此函数可以赋值、可以运算、可以拥有属性和方法,甚至可以临时存储值、构造实例等.

function 函数名(参数1,参数2,参数){ //注意,参数列表在函数中为局部变量
    
    let a = 50;
    let b = 100;
    
    return a + b;// return 代表终止执行并将 a+b 计算结果返回给调用者。
    a = 100; // 因为return的原因,该行代码不会执行。
}

​ 在JavaScript中,对象内储存的内容其实就是以键值对的方式存在

​ 如:{ A:“123” };

​ 这里值得一提的是,我们对象中的每一个属性包括对象本身,都会有三个特性,如下所示:

/*
* 属性特性:		
*	configurable
*		当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应* 的对象上被删除。简单来说,就是这个属性为flase的时候,就不能被删除
* 	enumerable
*		当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。
*	writable
*		当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变.
*/

2.1 create 创建一个对象

const obj = Object.create({a:1}, {b: {value: 2}})

第一个参数为对象,对象为函数调用之后返回新对象的原型对象,第二个参数为对象本身的实例方法(默认不能修改,不能枚举)
obj.__proto__.a === 1      // true 

obj.b = 3;
console.log(obj.b)      // 2

//创建一个可写的,可枚举的,可配置的属性p
obj2 = Object.create({}, {
  p: {
    value: 2,       // 属性值
    writable: true,     //  是否可以重写值
    enumerable: true,   //是否可枚举
    configurable: true  //是否可以修改以上几项配置
  }
});

obj2.p = 3;
console.log(obj2.p)     // 3

注意: enumerable 会影响以下
forin  遍历包括对象原型上属性

Object.keys()   只能遍历自身属性

JSON.stringify  只能序列化自身属性

2.2 defineProperty Object.defineProperty(object, prop, descriptor)

定义对象属性

添加数据属性
var obj = {};

// 1.添加一个数据属性
Object.defineProperty(obj, "newDataProperty", {
    value: 101,
    writable: true,
    enumerable: true,
    configurable: true
});

obj.newDataProperty    // 101

// 2.修改数据属性
Object.defineProperty(obj, "newDataProperty", {
    writable:false
});

//添加访问器属性
var obj = {};

Object.defineProperty(obj, "newAccessorProperty", {
    set: function (x) {
        this.otherProperty = x;
    },
    get: function () {
        return this.otherProperty;
    },
    enumerable: true,
    configurable: true
});
注意:  1.第一个参数必须为对象
        2.descriptor 不能同时具有 (value 或 writable 特性)(getset 特性)。
        3.configurable 为false 时,不能重新修改装饰器

2.3 Object.defineProperties(object, {prop1 : descriptor1, prop2 : descriptor2, …)

var obj = {};
Object.defineProperties(obj, {
  'property1': {
    value: true,
    writable: true
  },
  'property2': {
    value: 'Hello',
    writable: false
  }
  // etc. etc.
});

2.4 Object.keys

遍历可枚举的属性,只包含对象本身可枚举属性名称

let arr = ["a", "b", "c"];
let obj = { foo: "bar", baz: 42 };
let ArrayLike = { 0 : "a", 1 : "b", 2 : "c"};

Object.keys(arr)        // ['0', '1', '2']
Object.keys(obj)        // ["foo","baz"]
Object.keys(ArrayLike)  // ['0', '1', '2']

2.5 Object.values

遍历可枚举的属性值,只包含对象本身可枚举属性值

let arr = ["a", "b", "c"];
let obj = { foo: "bar", baz: 42 };
let ArrayLike = { 0 : "a", 1 : "b", 2 : "c"};

Object.values(arr)      // ["a", "b", "c"]
Object.values(obj)          // ["bar",42]
Object.values(ArrayLike)    // ["a", "b", "c"]

2.6 Object.getPrototypeOf

获取指定对象的原型(内部[[Prototype]]属性的值)

const prototype1 = {};
const object1 = Object.create(prototype1);

console.log(Object.getPrototypeOf(object1) === prototype1);   // true

注意:Object.getPrototypeOf(Object) 不是 Object.prototype
     Object.getPrototypeOf( Object ) === Function.prototype;  // true

2.7 Object.setPrototypeOf

设置一个指定的对象的原型

const obj = {a: 1}, proto = {b:2}

Object.setPrototypeOf(obj, proto)

obj.__proto__ === proto     //true

2.8 Object.getOwnPropertyNames

与keys相似,但包含遍历包含不可枚举属性

var my_obj = Object.create({}, {
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false
  }
});

my_obj.foo = 1;

Object.getOwnPropertyNames(my_obj).sort()   // ["foo", "getFoo"]

2.9 Object.getOwnPropertyDescriptor

获取该属性的描述对象

let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo')

//  { value: 123, writable: true, enumerable: true, configurable: true }

2.10 Object.getOwnPropertyDescriptors

返回指定对象所有自身属性(非继承属性)的描述对象

Object.getOwnPropertyDescriptors 方法,返回指定对象所有自身属性(非继承属性)的描述对象。

const obj = {
  foo: 123,
  get bar() { return 'abc' }
};
 
console.dir(Object.getOwnPropertyDescriptors(obj))
//   { foo:{ value: 123,
//      writable: true,
//      enumerable: true,
//      configurable: true },
//       bar:{ get: [Function: bar],
//      set: undefined,
//      enumerable: true,
//      configurable: true } 
//     }


使用场景:
Object.assign() 方法只能拷贝源对象的可枚举的自身属性,同时拷贝时无法拷贝属性的特性,而且访问器属性会被转换成数据属性,也无法拷贝源对象的原型

Object.create() 方法可以实现上面说的这些,配合getPrototypeOf,以及getOwnPropertyDescriptors实现全面浅拷贝

Object.create(
  Object.getPrototypeOf(obj), 
  Object.getOwnPropertyDescriptors(obj) 
);

2.11 Object.is

它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致

Object.is('foo', 'foo')     // true

Object.is({}, {})           // false

不同于 === 之处
+0 === -0                   //true
NaN === NaN                     // false

Object.is(+0, -0)           // false
Object.is(NaN, NaN)         // true

2.12 Object.hasOwnProperty

方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性

let o = {a: 1 }

o.hasOwnProperty('a')   //true
o.hasOwnProperty('b')   //false   对象自身没有属性b
o.hasOwnProperty('toString');  //false  不能检测对象原型链上的属性


如何遍历一个对象的所有自身属性,例子:
var buz = {
    fog: 'stack'
};

for (var name in buz) {
    if (buz.hasOwnProperty(name)) {
       console.log("this is fog (" + name + ") for sure. Value: " + buz[name]);
    }
    else {
       console.log(name); // toString or something else
    }
}

2.13 Object.isPrototypeOf

isPrototypeOf方法用于测试一个对象是否存在于另一个对象的原型链上

function Foo() {}
function Bar() {}
function Baz() {}

Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);

var baz = new Baz();

console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true

2.14 Object.getOwnPropertySymbols

var obj = {};
var a = Symbol("a");
var b = Symbol.for("b");

obj[a] = "localSymbol";
obj[b] = "globalSymbol";

var objectSymbols = Object.getOwnPropertySymbols(obj);

console.log(objectSymbols.length); // 2
console.log(objectSymbols)         // [Symbol(a), Symbol(b)]
console.log(objectSymbols[0])      // Symbol(a)

Object上还含有三个更改对象指向的方法,这个我们放在作用域处进行讲解。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰履踏青云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值