一切都是对象,对象是若干属性的集合
- 数组是对象、函数是对象、对象还是对象。对象里面的一切都是属性,只有属性,没有方法。方法也是属性。
- 一切引用类型都是属性
- 怎么判断一个值是否是对象?
- 值类型的类型判断用 typeof , 引用类型的类型判断用 instanceof
- 对象都是通过函数创建的 // 对象是由构造函数 Object() 创建的
对象字面量
- 对象字面量:对象字面量是一个名/值对 列表,每个名/值对之间用逗号分隔。
- 使用对象字面量可以创建单个对象,语义直观
var person={ name:"dog", age:20, };
- 对象字面量可以嵌套
var person={ name:"dog", age:20, getNmae:function(){ return this.name; } };
- 对象字面量也可以先创建,再添加属性和方法
var person={}; person.name="age"; person.age=20; person.getName=function(){ return this.name; }
创建对象
- 使用Object构造函数创建对对象
var obj=new Object(); obj.name="dog"; obj.getName=function(){ return this.name; }
- 使用字面量创建对象
- 自定义构造函数创建对象
function Person(name,age){ this.name=name; this.age=age; } var person=new Person("dog",20);
原型
- 每一个函数function都有一个prototype , 即原型。 prototype有一个默认的属性constructor , 指向这个函数本身
function Foo(){ }; console.log(Foo.prototype); //Object{} console.log(Foo.prototype .constructor); // function Foo(){}
- 每一个对象都有一个__proto__ ( 隐式原型 ) , 指向创建该对象的函数的prototype
function Foo(){}; console.log(Foo.prototype); //Object{} var f=new Foo(); console.log(f.__proto__); // Object{} console.log(Foo.prototype==f.__proto__) ; // true
Prototype
- 通过构造函数生成实例对象时,会自动为实例对象分配原型对象。每一个构造函数都有一个prototype属性 ,这个属性就是实例对象的原型对象。
- 原型对象上所有的属性和方法,都能被派生对象共享。 原型对象的作用就是定义所有实例对象共享的属性和方法
function animal(name){ this.name=name; } animal.prototype.color="white"; var cat1=new animal("cat"); var cat2=new animal('dog'); cat1.color; //white cat2.color; //white cat1.color==cat2.color; // true
- 当实例对象本身没有某个属性或方法时,他会到构造函数的prototype属性指向的对象,去寻找该属性或方法
- 属性的覆盖
function Foo(){}; Foo.prototype.name="cat"; var f1=new Foo(); var f2=new Foo(); f1.name="dog"; console.log(f1.name); //dog 来自实例 console.log(f2.name); // cat 来自原型
- 使用字面量为原型添加属性时,会重写原型对象。重写原型对象会切断现有原型与之前已经存在的实例对象的之间关系
//不重写原型对象 function Foo(){}; var f1=new Foo(); Foo.prototype.name="cat"; Foo.prototype.getName=function(){ return this.name; //this指向调用该构造函数的实例对象 } f1.getName(); //cat //使用字面量重写原型对象 function Foo(){}; var f1=new Foo(); Foo.prototype={ name:"cat", getName:function(){ return this.name } } f1.getNmae(); // Uncaught TypeError:f1.getName is not a function(...) //因为重写原型对象断开了原型与已有对象的联系 解决方法:在重写之后再创建对象就可以了 var f2=new Foo(); f2.getName(); //cat;
- 对于属性值是引用类型的原型属性,修改其中一个实例的属性,其他实例的该属性也会随之改变。
function Foo(){}; Foo.prototype={ name:"cat", friends:['dog','xhdsh']; getName:function(){ return this.name } } var f1=new Foo(); var f2=new Foo(); f1.name="hh"; f1.friends=['hhhh','ssss']; console.log(f2.name); // cat //name是值类型,修改f1的name属性并不会影响其他实例对象该属性的值 console.log(f2.friends); // ['hhh'] //friends为引用类型,故修改f1.friends后f2.friends也会随之改变
__proto__
- __proto__是一个隐藏的属性
- Object.prototype 是一个特例 ,它的 __proto__ 指向null
- 函数也是对象,故函数也有隐式原型。函数是由构造函数 Function(){} 创建的,所以函数的 __proto__ 指向 Function(){} 的prototype
function Foo(){}; console.log(Foo.__proto__); //function(){} console.log(Function.prototype); //function(){} console.log(Foo.__proto__==Function.prototype); //true
- 需要注意的一点是 ,Function是由构造函数Function(){} ( 即它本身) 创建的,所以Function.__proto__==Function.prototype。 另外 , Fuction,prototype是一个对象,故Function.prototype.__proto__==Object.prototype.
console.log(Function instanceof Function); //true console.log(Function.prototype.__proto__); // Object{}
- 注解: istanceof 运算符的实质:它依次与实例对象的所有原型对象的 constructor属性进行比较,只要有一个符合就返回true,否则返回false
原型链
- 对象的属性和方法,有可能是定义在自身,也有可能是定义在它的原型对象。由于原型本身也是对象,又有自己的原型,所以形成了一条原型链。
- 原型链理解: 访问一个对象的属性时,先在基本属性中查找,如果没有再沿着__proto__这条链向上找,这就是原型链
- 原型链的作用:读取对象的某个属性时,JavaScript引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。如果直到最顶层的Object.prototype还是找不到,则返回undefined
- 如果一层层地上溯,所有对象的原型最终都可以上溯到 Object.prototype
- javascript中的继承是通过原型链来体现的
- 原型属性过滤
- 过滤原型属性——hasOwnProperty : 用来判断一个对象是否有你给出名称的属性或对象。此方法无法检查对象的原型链中是具有该属性,该属性必须是对象本身的一个成员。
function Foo(){}; var f=new Foo(); Foo.prototype.age=12; f.name="dog"; console.log(f.age); console.log(f.hasOwnProperty('name')); //true console.log(f.hasOwnProperty('age')); //false
- 过滤原型属性——hasOwnProperty : 用来判断一个对象是否有你给出名称的属性或对象。此方法无法检查对象的原型链中是具有该属性,该属性必须是对象本身的一个成员。
-
- isPrototypeOf : 用来判断要检查其原型链的对象是否存在于指定对象实例中,是则返回true , 否则返回false
function Foo(){};Foo.prototype.age=12;var f=new Foo();console.log(Foo.prototype.isPrototypeOf(f)); //true
- isPrototypeOf : 用来判断要检查其原型链的对象是否存在于指定对象实例中,是则返回true , 否则返回false
- 获取属性
- for ( var prototype in obj) : 返回所有通过对象可访问的,可枚举的属性
- Object.keys(obj) ; 返回一个包含所有可枚举属性的字符串数组
- Object.getOwnPrototypeNames(obj) ; 返回所有的实例属性,无论是否可枚举
- 获取原型属性
- Object.getPrototypeOf () : 返回一个对象的原型
function Foo(){}; Foo.prototype.age=12; var f=new Foo(); f.name="dog"; console.log(Object.getPrototypeOf(f)); // Object{age:12}
- Object.getPrototypeOf () : 返回一个对象的原型
-
- Object.setPrototypeOf () : 可以为现有对象设置原型,返回一个新对象。该方法接受两个参数,第一个是现有对象。第二个是原型对象。
var a={age:12}; var b=Object.setPrototypeOf({},a); console.log(b.age); //12
- Object.setPrototypeOf () : 可以为现有对象设置原型,返回一个新对象。该方法接受两个参数,第一个是现有对象。第二个是原型对象。