1. 内建对象
由ES标准中定义的对象,在任何ES的实现中都可以使用
eg:Math String Number Boolean Function Object 。。。
2. 宿主对象
由JS的运行环境提供的对象,目前来说主要指由浏览器提供的对象
eg:BOM DOM
3. 自定义对象
我们自己创建的对象
1. 创建
var obj=new Object();
var obj={
name:"你猜",
age:"不告诉你",
gender:"待定...",
son:{
say:"hello world",
}
};
对象是可以嵌套的。
2. 属性的添加
obj.newProperty="我是新来的";
3. 属性的删除
delete obj.name;
eg:obj.var="hello";
但是如果使用特殊的属性名,不能采用 obj.property 方法,需要使用另一种方式。
obj["property"]=value;
需要注意的是,读取任然需要采用此种方式。
读取:console.log(obj["property"]);
in运算符
通过该运算符检查一个对象中是否含有指定的属性值
语法:"property" in obj;
通过 in 运算符搭配 for 循环遍历对象
for (var n in obj){
console.log("属性名:"+n);
console.log("属性值:"+obj[n]);
}
var a=new Object();
a.name="hello"; //a 中name
var b= a;
console.log(b.name); //改变b中那么
b.name="world";
console.log(a.name); //a中name随之改变
对象的属性指向一个函数,即为方法。
var obj={
name:"你猜",
age:"不告诉你",
gender:"待定...",
saytoyou:function () { //创建方法
alert("哈喽...");
}
};
obj.saytoyou(); //方法的调用
1.以函数形式调用,this永远是window
2.以方法形式调用,this就是调用方法的那个对象
eg:
function fun() {
console.log("this对象是:"+this+" name:"+this.name);
}
var obj={
name:"你猜",
age:"不告诉你",
gender:"待定...",
fun:fun
};
fun();
obj.fun();
function createPerson(name,age,gender) {
var obj=new Object();
obj.name=name;
obj.age=age;
obj.gender=gender;
obj.sayhello=function () {
console.log("name:"+this.name);
}
return obj;
}
var obj1=createPerson("猪八戒",11,"女");
var obj2=createPerson("蜘蛛精",22,"男");
console.log(bj1);
console.log(obj2);
obj1.sayhello();
obj2.sayhello();
function Person(name,age,gender) {
this.name=name;
this.age=age;
this.gender=gender;
this.sayhello=function () {
console.log("use constructor,name:"+this.name);
}
}
var per1=new Person("猪八戒",11,"女");
var per2=new Person("蜘蛛精",22,"男");
console.log(per1);
console.log(per2);
per1.sayhello();
per2.sayhello();
应该可以很明显的看出差别了吧。
差别:对象名字不再是空或者Object,而是构造函数的名字,比如浏览器对象window:
语法:obj instanceof constructor;
如果是,返回true,否则返回false
已经谈了两种方式来创建对象,哪个好,哪个不好,心里也有点点*数了,那么就对那个好点点来一点点改造吧。(*.*)
对于这一块代码
function Person(name,age,gender) {
this.name=name;
this.age=age;
this.gender=gender;
this.sayhello=function () {
console.log("use constructor,name:"+this.name);
}
}
那个function每创建一个对象,就要重新分配内存,但是他实现的功能就是把自己父亲的的儿子的属性值打印出来,实际我们每次调用方法时只需要传进去对象,前面说过this是哪个对象方法调用,就是那个对象的属性值。
改进:
function sayhello() {
console.log("use constructor,name:"+this.name);
}
function Person(name,age,gender) {
this.name=name;
this.age=age;
this.gender=gender;
this.sayhello=sayhello;
}
var per1=new Person("猪八戒",11,"女");
var per2=new Person("蜘蛛精",22,"男");
console.log(per1);
console.log(per2);
per1.sayhello();
per2.sayhello();
上面的构造函数的改造貌似很成功?成功的话,下面的口水话我也就不说了。
reason:
- 将方法在全局作用域中定义,污染了全局作用域的命名空间
- 而且定义在全局作用域中也不安全
特别说明
原型的调用
使用
obj.__proto__;
来调用原型对象。
function Person(name,age,gender) {
this.name=name;
this.age=age;
this.gender=gender;
}
var per1=new Person("猪八戒",11,"女");
var per2=new Person("蜘蛛精",22,"男");
console.log("第一层:"+per1.__proto__);
console.log("第二层:"+per1.__proto__.__proto__);
console.log("第三层:"+per1.__proto__.__proto__.__proto__);
使用原型对象创建公共的区域
function Person(name,age,gender) {
this.name=name;
this.age=age;
this.gender=gender;
}
Person.prototype.sayhello=function () {
console.log(this.name);
}
var per1=new Person("猪八戒",11,"女");
var per2=new Person("蜘蛛精",22,"男");
per1.sayhello();
per2.sayhello();
结果
虽然并没有直接在对象中创建方法,但是在原型对象中创建了方法,根据儿子---->父亲---->爷爷。。。一层层找到了方法。
查看方法的归属(使用"property" in obj
查看)
function Person(name,age,gender) {
this.name=name;
this.age=age;
this.gender=gender;
}
Person.prototype.sayhello=function () {
console.log(this.name);
}
var per1=new Person("猪八戒",11,"女");
var per2=new Person("蜘蛛精",22,"男");
console.log("sayhello" in per1);
console.log("sayhello" in per2);
结果
调皮,竟然都是其包含的方法,换个姿势。
查看方法的归属(使用"obj.hasOwnProperty("function")
查看)
function Person(name,age,gender) {
this.name=name;
this.age=age;
this.gender=gender;
}
Person.prototype.sayhello=function () {
console.log(this.name);
}
var per1=new Person("猪八戒",11,"女");
var per2=new Person("蜘蛛精",22,"男");
console.log("使用in方法");
console.log("sayhello" in per1);
console.log("sayhello" in per2);
console.log("使用 hasOwnProperty 第零层");
console.log(per1.hasOwnProperty("sayhello"));
console.log(per2.hasOwnProperty("sayhello"));
console.log("使用 hasOwnProperty 第一层");
console.log(per1.__proto__.hasOwnProperty("sayhello"));
console.log(per2.__proto__.hasOwnProperty("sayhello"));
console.log("使用 hasOwnProperty 第二层");
console.log(per1.__proto__.__proto__.hasOwnProperty("sayhello"));
console.log(per2.__proto__.__proto__.hasOwnProperty("sayhello"));
结果
然后就知道了方法隶属于第一层。
这个地方我就有个疑问了。创建的方法就是obj.prototype.fun=function;
我改成obj.prototype.prototype.fun=function;
不就是第二层了。
结果可想而知,自己试咯。(*.*)。
如果原型对象中的方法和自己创建的方法相同,使用谁?
function Person(name,age,gender) {
this.name=name;
this.age=age;
this.gender=gender;
}
Person.prototype.sayhello=function () {
console.log("我是原型对象中的");
}
var per1=new Person("猪八戒",11,"女");
per1.sayhello=function () {
console.log("我是自己创建的哈");
}
console.log(Person.prototype==per1.__proto__);
console.log(per1.sayhello());
对于hasOwnProperty()
方法的疑惑.
虽然在使用这个方法,但是并没有明确定义,这个方法出自哪里,我已经猜到了。。。看哈结果
console.log("第零层:"+per1.hasOwnProperty("hasOwnProperty"));
console.log("第一层:"+per1.__proto__.hasOwnProperty("hasOwnProperty"));
console.log("第二层:"+per1.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));
前面说到原型对象,这里再对他深掏一波。
每个对象都有toString方法,
function Person(name,age,gender) {
this.name=name;
this.age=age;
this.gender=gender;
}
Person.prototype.sayhello=function () {
console.log(this.name);
}
var per1=new Person("猪八戒",11,"女");
console.log(per1.toString());
得到了一个对象,看一下他属于哪一个对象。
function Person(name,age,gender) {
this.name=name;
this.age=age;
this.gender=gender;
}
Person.prototype.sayhello=function () {
console.log(this.name);
}
var per1=new Person("猪八戒",11,"女");
console.log("第一层:"+per1.__proto__.hasOwnProperty("toString"));
console.log("第二层:"+per1.__proto__.__proto__.hasOwnProperty("toString"));
到此,就来改一哈toString()
,让他返回具体的值.
思路:在第一层原型对象中进行方法的添加,适用所有类似的对象
function Person(name,age,gender) {
this.name=name;
this.age=age;
this.gender=gender;
}
Person.prototype.sayhello=function () {
console.log(this.name);
}
Person.prototype.toString=function () {
console.log("name:"+this.name+",age:"+this.age+",gender:"+this.gender);
}
var per1=new Person("猪八戒",11,"女");
console.log(per1.toString());
结果
告辞。