文章目录
- 1. JS 中的变量声明
- 2. JS中的Object对象及静态方法
- 2.1 create 创建一个对象
- 2.2 defineProperty Object.defineProperty(object, prop, descriptor)
- 2.3 Object.defineProperties(object, {prop1 : descriptor1, prop2 : descriptor2, ...)
- 2.4 Object.keys
- 2.5 Object.values
- 2.6 Object.getPrototypeOf
- 2.7 Object.setPrototypeOf
- 2.8 Object.getOwnPropertyNames
- 2.9 Object.getOwnPropertyDescriptor
- 2.10 Object.getOwnPropertyDescriptors
- 2.11 Object.is
- 2.12 Object.hasOwnProperty
- 2.13 Object.isPrototypeOf
- 2.14 Object.getOwnPropertySymbols
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 会影响以下
for…in 遍历包括对象原型上属性
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 特性)(get 或 set 特性)。
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上还含有三个更改对象指向的方法,这个我们放在作用域处进行讲解。