对象应用"/>
ES6对象应用
对象的创建和销毁都在JavaScript执行过程中发生,理解这种范式的含义对于理解整个语言非常重要。
JavaScript对象应用
- 声明和实例化
- 对象解构
- 1、嵌套解构
- 对象的引用
- 对象废除
- 早绑定和晚绑定
- 对象作用域
- 公用、私有和受保护的作用域
- 关键字this
- 静态作用域
声明和实例化
对象的创建方式是用关键字new后面跟上了实例化的类的名字。
var oObject = new Object();
var oStringObject = new String();
第一行代码创建了 Object 类的一个实例,并把它存储到变量 oObject 中。第二行代码创建了 String 类的一个实例,把它存储在变量 oStringObject 中。如果构造函数无参数,括号则不是必需的。因此可以采用下面的形式重写上面的两行代码:
var oObject = new Object;
var oStringObject = new String;
对象解构
ES6新增了对象的解构语法,可以在一条语句中实现使用嵌套数据实现一个或者多个赋值操作。简单而言,对象解构就是使用和对象匹配的解构来实现对象属性赋值。
给出如下例子,展示了两段等价代码,首先是不适用对象解构:
// 不适用对象解构
let person = {name: 'csdn',age: 23
};
let personName = person.name;
let personAge = person.age;console.log(personName);
console.log(personAge);
接下来使用对象解构:
// 使用了对象结构
let person = {name: 'csdn',age: 23
};
let { name: personName, age: personAge } = person;
console.log(personName);
console.log(personAge);
利用了解构,可以实现在一个类似对象字面量的结构中,声明多个变量,同时执行多个变量,然后执行多个赋值操作,若想让变量直接使用属性的名称,则可以使用间歇操作,如下所示:
let person = { name: 'Matt', age: 27
};
let { name, age } = person;
console.log(name); // Matt
console.log(age); // 27
解构赋值不一定和对象的属性匹配。赋值的时候会忽略某些属性,若引用的属性不存在,则该变量的数值就是undefined。
let person = { name: 'Matt', age: 27
};
let { name, job } = person;
console.log(name); // Matt
console.log(job); // undefined
解构在内部使用函数ToObject()
(不能够在运行时环境中直接访问)把源数据结构转换为对象。这意味着在对象解构的上下文中,原始值会被当做一个对象,这也意味着:null和undefined都不能够被解构
,否则抛出异常。
let { length } = 'foobar';
console.log(length); // 6
let { constructor: c } = 4;
console.log(c === Number); // true
let { _ } = null; // TypeError
let { _ } = undefined; // TypeError
解构不要求变量在解构表达式中声明。但是,若事先声明的变量赋值,则赋值表达式必须包含在一对括号中:
let personName, personAge;
let person = { name: 'Matt', age: 27
};
({name: personName, age: personAge} = person);
console.log(personName, personAge); // Matt, 27
1、嵌套解构
解构对于引用嵌套的属性或者赋值目标没有限制。可以通过解构来复制对象属性:
let person = { name: 'Matt', age: 27, job: { title: 'Software engineer' }
};
let personCopy = {};
({ name: personCopy.name, age: personCopy.age, job: personCopy.job
} = person);
// 因为一个对象的引用被赋值给 personCopy,所以修改
// person.job 对象的属性也会影响 personCopy
person.job.title = 'Hacker'
console.log(person);
// { name: 'Matt', age: 27, job: { title: 'Hacker' } }
console.log(personCopy);
// { name: 'Matt', age: 27, job: { title: 'Hacker' } }
解构赋值可以使用嵌套解构,匹配嵌套的属性:
name: 'Matt', age: 27, job: { title: 'Software engineer' }
};
// 声明 title 变量并将 person.job.title 的值赋给它
let { job: { title } } = person;
console.log(title); // Software engineer
在外层属性没有定义的情况下不能使用嵌套解构。无论源对象还是目标对象都一样:
let person = { job: { title: 'Software engineer' }
};
let personCopy = {};
// foo 在源对象上是 undefined
({ foo: { bar: personCopy.bar }
} = person);
// TypeError: Cannot destructure property 'bar' of 'undefined' or 'null'.
// job 在目标对象上是 undefined
({ job: { title: personCopy.job.title }
} = person);
// TypeError: Cannot set property 'title' of undefined
对象的引用
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
对象废除
ES拥有无用存储单元收集程序(garbage collection routine),意味着不用专门销毁对象来释放内存。当再没有对对象的引用时,称该对象被废除(dereference)了。运行无用存储单元收集程序时,所有废除的对象都被销毁。每当函数执行完它的代码,无用存储单元收集程序都会运行,释放所有的局部变量,还有在一些其他不可预知的情况下,无用存储单元收集程序也会运行。
把对象的所有引用都设置为 null,可以强制性地废除对象。例如:
var oObject = new Object;
// do something with the object here
oObject = null;
当变量 oObject 设置为 null 后,对第一个创建的对象的引用就不存在了。这意味着下次运行无用存储单元收集程序时,该对象将被销毁。
每用完一个对象之后,就将其废除,释放内存,可以确保不再使用已经不能访问的对象,从而防止程序设计错误的出现,另外旧的浏览器例如IE/MAC没有全面的无用存储单元收集程序,所以在卸载页面时,对象可能不会被正确的销毁。
废除对象和它的所有特性是确保内存使用正确的最好方法。
注意:废除对象的所用引用需要当心,若一个对象有两个或者多个引用,则需要正确废除该对象,必须把其所有应用都设置为null。
早绑定和晚绑定
绑定:
把对象的接口和对象实例结合在一起的方法。
早绑定(early binding)是指在实例化对象之前定义它的属性和方法,这样编译器或解释程序就能够提前转换机器代码。在 Java 和 Visual Basic 这样的语言中,有了早绑定,就可以在开发环境中使用 IntelliSense(即给开发者提供对象中属性和方法列表的功能)。ECMAScript 不是强类型语言,所以不支持早绑定。
晚绑定(late binding)指的是编译器或解释程序在运行前,不知道对象的类型。使用晚绑定,无需检查对象的类型,只需检查对象是否支持属性和方法即可。ECMAScript 中的所有变量都采用晚绑定方法。这样就允许执行大量的对象操作,而无任何惩罚。
对象作用域
作用域指的就是变量的适用范围。
公用、私有和受保护的作用域
在传统的面向对象程序设计中,主要关注于公用和私有作用域。公用作用域中的对象属性可以从对象外部访问,即开发者创建对象的实例后,就可使用它的公用属性。而私有作用域中的属性只能在对象内部访问,即对于外部世界来说,这些属性并不存在。这意味着如果类定义了私有属性和方法,则它的子类也不能访问这些属性和方法。
受保护作用域也是用于定义私有的属性和方法,只是这些属性和方法还能被其子类访问。
ECMAScript 只有公用作用域
对 ECMAScript 讨论上面这些作用域几乎毫无意义,因为 ECMAScript 中只存在一种作用域 - 公用作用域。ECMAScript 中的所有对象的所有属性和方法都是公用的。因此,定义自己的类和对象时,必须格外小心。记住,所有属性和方法默认都是公用的!
建议的办法:在属性前后加上下划线,
obj._color_ = "blue";
这段代码中,属性color是私有的。注意下划线并不能改变属性是公用属性的事实,只是告诉其他开发者,应该把属性看做是私有的。
关键字this
在 ECMAScript 中,要掌握的最重要的概念之一是关键字 this 的用法,它用在对象的方法中。关键字 this 总是指向调用该方法的对象:
var oCar = new Object;
oCar.color = "red";
oCar.showColor = function() {alert(this.color);
};oCar.showColor(); //输出 "red"
在上面的方法中,关键字this在对象的showCar方法中,在此环境中,this等于onCar,如下代码可以实现相同的功能:
var oCar = new Object;
oCar.color = "red";
oCar.showColor = function() {alert(oCar.color);
};oCar.showColor(); //输出 "red"
静态作用域
静态作用域定义的属性或者方法任何时候都能够从同一个位置访问。累可以具有属性和方法,不需要实例化该类的对象,就可以访问这些属性和方法,例如java的URLEncoder类方法,URLEncoder方法概述。
ECMAScript 没有静态作用域
严格来说,ECMAScript 并没有静态作用域。不过,它可以给构造函数提供属性和方法。还记得吗,构造函数只是函数。函数是对象,对象可以有属性和方法。例如:
function sayHello() {alert("hello");
}sayHello.alternate = function() {alert("hi");
}sayHello(); //输出 "hello"
sayHello.alternate(); //输出 "hi"
在这里方法alternate实际上是函数sayHello
的方法,可以类似调用常规函数一样调用sayHello
输出hello,不过其并不是静态的方法。
更多推荐
ES6对象应用
发布评论