// 二、通过构造函数来创建对象functionPerson(name, age){// 这是构造函数(也称为对象原型), You是对象实例// 使用 this 将传入函数的值赋给对象的属性this.name = name;this.age = age;}// new一个person对象,用You接收let You =newPerson('You',24);// 点表示法操作属性
You.name ='Simon';let name = You.name;// 括号表示法操作属性
You['name']='Simon';let name = You['name'];// 括号表示法可以被用来访问以预留关键字作为名称的属性的值,但是不会被编辑器优化
obj.for ='Simon';// 语法错误,因为 for 是一个预留关键字
obj["for"]='Simon';// 工作正常// 可以使用变量定义键let user =prompt('what is your key?');
obj[user]=prompt('what is its value?');
// 让我们从一个函数里创建一个对象 o,它自身拥有属性 a 和 b:letf=function(){this.a =1;this.b =2;}/* 这么写也一样
function f() {
this.a = 1;
this.b = 2;
}
*/let o =newf();// {a: 1, b: 2}// 在 f 函数的原型上定义属性
f.prototype.b =3;
f.prototype.c =4;// 不要在 f 函数的原型上直接定义 f.prototype = {b:3,c:4};这样会直接打破原型链// o.[[Prototype]] 有属性 b 和 c (其实就是 o.__proto__ 或者 o.constructor.prototype)// o.[[Prototype]].[[Prototype]] 是 Object.prototype.// 最后 o.[[Prototype]].[[Prototype]].[[Prototype]] 是 null// 这就是原型链的末尾,即 null,根据定义,null 就是没有 [[Prototype]]。// 综上所述,整个原型链如下:// {a:1, b:2} ---> {b:3, c:4} ---> Object.prototype---> null
console.log(o.a);// 1// a 是 o 的自身属性吗?是的,该属性的值为 1
console.log(o.b);// 2// b 是 o 的自身属性吗?是的,该属性的值为 2// 原型上也有一个'b'属性,但是它不会被访问到。// 这种情况被称为"属性遮蔽 (property shadowing)"
console.log(o.c);// 4// c 是 o 的自身属性吗?不是,那看看它的原型上有没有// c 是 o.[[Prototype]] 的属性吗?是的,该属性的值为 4
console.log(o.d);// undefined// d 是 o 的自身属性吗?不是,那看看它的原型上有没有// d 是 o.[[Prototype]] 的属性吗?不是,那看看它的原型上有没有// o.[[Prototype]].[[Prototype]] 为 null,停止搜索// 找不到 d 属性,返回 undefined
2.1.2、继承方法
// 当继承的函数被调用时,this 指向的是当前继承的对象,而不是继承的函数所在的原型对象。var o ={a:2,m:function(){returnthis.a +1;}};
console.log(o.m());// 3 ,当调用 o.m 时,'this' 指向了 ovar p = Object.create(o);// p 是一个继承自 o 的对象
p.a =4;// 创建 p 的自身属性 'a'
console.log(p.m());// 5// 调用 p.m 时,'this' 指向了 p// 又因为 p 继承了 o 的 m 函数// 所以,此时的 'this.a' 即 p.a,就是 p 的自身属性 'a'
2.2、不同方式所生成的原型链
2.2.1、使用语法结构
var o ={a:1};// o 这个对象继承了 Object.prototype 上面的所有属性// o 自身没有名为 hasOwnProperty 的属性,hasOwnProperty 是 Object.prototype 的属性// 因此 o 继承了 Object.prototype 的 hasOwnProperty, Object.prototype 的原型为 null// 原型链如下:// o ---> Object.prototype ---> nullvar a =["yo","whadup","?"];// 数组都继承于 Array.prototype ,(Array.prototype 中包含 indexOf, forEach 等方法)// 原型链如下:// a ---> Array.prototype ---> Object.prototype ---> nullfunctionf(){return2;}// 函数都继承于 Function.prototype ,(Function.prototype 中包含 call, bind 等方法)// 原型链如下:// f ---> Function.prototype ---> Object.prototype ---> null
2.2.2、使用构造器
functionGraph(){this.vertices =[];this.edges =[];}Graph.prototype ={addVertex:function(v){this.vertices.push(v);}};var g =newGraph();// g 是生成的对象,他的自身属性有 'vertices' 和 'edges'。// 在 g 被实例化时,g.[[Prototype]] 指向了 Graph.prototype。
2.2.3、使用Object.create()
var a ={a:1};// a ---> Object.prototype ---> null// ES5新增的方法,可以调用这个方法来创建一个新对象。新对象的原型就是调用 create 方法时传入的第一个参数:var b = Object.create(a);// b ---> a ---> Object.prototype ---> null
console.log(b.a);// 1 (继承而来)var c = Object.create(b);// c ---> b ---> a ---> Object.prototype ---> nullvar d = Object.create(null);// d ---> null
console.log(d.hasOwnProperty);// undefined,因为 d 没有继承 Object.prototype