不包括原型部分 6.1.1~6.2.2
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script>
var obj = {
name: "Harold",
age: 21,
job: "student",
boolean: true,
method: function test () {
console.log(this.job);
}
}
// console.log(obj.name);
// obj.method();
// for(i in obj){
// console.log(i);
// }
// //ECMAScript中的属性分为:数据属性、访问器属性
// //数据属性:包含一个数据值的位置,在这个位置可以进行读取或写入值,用以下特性描述其行为
// // [[Configurable]] 能否通过delete删除属性从而重新定义 能否修改属性特性 能否把属性修改为访问器属性
// // [[Enumerable]] 能否通过for-in循环返回属性
// // [[Writable]] 能否修改属性值 注意与第一个区分
// // 直接在对象中定义的属性 前面三个默认为true
// // [[Value]] 这个属性的数据值 默认为undefined
// //只能使用Object.defineProperty()方法
Object.defineProperty(obj, "name", {
writable: false,
// value: "linbudu"
});
obj.name = "linbudu";//把Writable改为false后会发现无法指定新的属性值了!
console.log(obj.name);
Object.defineProperty(obj,"name", {
configurable:false,
value: "budu",
});
console.log(obj.name);//budu
// Object.defineProperty(obj,"name", {
// configurable:true,
// value: budu,
// });//抛出错误:一旦把属性定为不可配置的,就无法再修改回去了 如果原先就是false还可以
// //注意 当调用此方法创建一个新属性时 前三个特性的默认值都是false
// //访问器属性 不包含数据值,而是包含getter(读取访问器属性时,负责返回有效的值)
// //与setter(在写入访问器属性时调用setter并传入新值,由这个函数决定如何处理数据)函数
// // [[Configurable]] 能否通过delete删除属性从而重新定义 能否修改属性特性 能否把属性修改为访问器属性
// // [[Enumerable]] 能否通过for-in循环返回属性
var reward = {
_year: 0,
ward: 1000
};
Object.defineProperty(reward, "_year", {
get: function(){
return this._year;
},
set: function(newValue){
if(newValue > 0){
this._year = newValue;
this.ward = (newValue - _year);
}
}
});
reward.year = 5;
console.log(reward.ward);//5
//_记号常常用于表示 只能通过对象方法访问的属性
var obj2 = {};
Object.defineProperties(obj2,{
name: {
writable: true,
value: "joyce"
},
age:{
configurable: true,
}})
console.log(obj2.name);
//读取属性的特性
var attr = Object.getOwnPropertyDescriptor(obj2,"name");
console.log(attr.value);//joyce
console.log(attr.configurable);//false 详见行48注释
//可以对任何对象使用此方法
var attr_window = Object.getOwnPropertyDescriptor(Document,"name");
console.log(attr_window.configurable);//true~ yup!
//创建对象
//Object构造函数与字面量都可以用来创建单个对象,但这些方法使用同一个接口创建
//多个对象,会产生大量的重复代码
//工厂模式 用函数来封装以特定接口创建对象的细节
function createObj(name,age,dream){
var o = new Object;
o.name = name;
o.age = age;
o.dream = dream;
o.method = function(){
alert("Having some Chicken's Blood!")
};
return o;//将o返回给要创建的对象
}
var day1 = createObj("Harold",21,"To be a Front-end development engineer");
var day2 = createObj("Joyce","19","Not now~");
console.log(day1.name);
// day1.method();
//解决了创建多个相似对象的问题,但没有解决对象识别的问题
//构造函数模式
// 创建自定义的构造函数 来定义自定义对象类型的属性与方法
function createFunc (name,age,job) {
this.name = name;
this.age = age;
this.job = job;
// this.method = Mom;
}
function Mom(){
alert(this.name);
}
var day3 = new createFunc("budu",21,"student");
console.log(day3.job);
//注意:这里没有显式的创建对象 直接将属性与方法赋给了this对象 没有return语句
//按照惯例 构造函数始终都应该以一个大写字母开头 构造函数本身也是函数 但可用来创建对象而已
//使用new操作符创建createFunc的新实例过程包括:创建一个新对象{},将执行函数的作用域赋给这个新对象(则this指向这个新对象)
//执行构造函数中的代码(添加属性和方法),返回新对象
//使用这种方法创建的新对象包含着构造函数的不同实例 且都具有constructor属性 并指向createFunc
console.log(day3.constructor);//返回构造函数的源代码
//这些对象既是Object的实例(所有对象都继承自Object),也是createFunc的实例
console.log(day3 instanceof Object);
console.log(day2 instanceof Object);
console.log(day3 instanceof createFunc);
//在另一个对象的作用域中调用构造函数
var obj3 = {
name:"Harold",
age:18,
// job:none 这边有几个属性 下面call()就要传进去几个参数 否则会出错
};
createFunc.call(obj3,"Joyce",20);
console.log(obj3.name);
//在obj3的作用域中调用后 他就拥有了这些属性与方法
//构造函数的主要问题:每个方法都要在每个实例上重新创建一遍 即:两个对象拥有的方法不是同一个Function对象的实例
//不同实例上的同名函数并不相同
//改进方法- 行118~122 这样一来,新创建的对象会共享在全局作用域中定义的同一个函数(引用类型的定义)
//然而这个函数虽然定义在全局作用域中 但实际只能被某个对象调用 全局毫无意义
//并且如果对象需要定义许多方法 那么就要在全局作用域中定义多个全局函数 那么这个自定义的引用类型(注意这里说的是Function,
//使用它作为方法这只是引用过程)
</script>
</body>
</html>