3.我需要对象吗?

对象的分类

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随之改变

3.我需要对象吗?_第1张图片

  • 执行b=null; 后,b的地址为空,将不再控制0x123地址的内容
    3.我需要对象吗?_第2张图片

this的那些事

    先谈谈对象的方法吧

对象的属性指向一个函数,即为方法。

var obj={
    name:"你猜",
    age:"不告诉你",
    gender:"待定...",
    saytoyou:function () {			//创建方法
        alert("哈喽...");
    }
};

obj.saytoyou();						//方法的调用

    this的说明

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
在这里插入图片描述

    根据上面不是很详细的描述,我们利用这点可以使用 instanceof 来检查一个对象是否是一个类的实例

    语法obj instanceof constructor;
    如果是,返回true,否则返回false

  • 注意,所有对象都是Object的后代

对构造函数的修改

已经谈了两种方式来创建对象,哪个好,哪个不好,心里也有点点*数了,那么就对那个好点点来一点点改造吧。(*.*)

    对于这一块代码

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:

  • 将方法在全局作用域中定义,污染了全局作用域的命名空间
  • 而且定义在全局作用域中也不安全

特别说明

  • 函数作为普通函数调用protatype没有任何作用和意义
  • 函数作为构造函数形式调用时,他所创建的对象就有一个隐含的属性

原型的调用

使用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"));

        结果
3.我需要对象吗?_第3张图片
        然后就知道了方法隶属于第一层。
        这个地方我就有个疑问了。创建的方法就是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()方法的改进

        前面说到原型对象,这里再对他深掏一波。
        每个对象都有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());

        结果
在这里插入图片描述
告辞。

你可能感兴趣的:(JavaScript)