JavaScript 对象的属性与创建方式

理解对象:数据属性和访问器属性。
创建对象:工厂模式、构造函数模式、原型模式、组合使用构造函数和原型模式、动态原型模式、寄生构造函数模式、稳妥构造函数模式。

1. 对象的属性 property

2.1 数据属性

行为特性:

  • configurable 能否删除
  • enumerable 能不能通过for in
  • writable 能否修改
  • value 设定属性值
Object.defineProperty(person, "name", {
    configurable: false,
    value: "Nicholas"
});

2.2 访问器属性

  • configurable 能否删除
  • enumerable 能不能通过for in
  • get
  • set

访问器属性不包含数据值;它们包含一对儿 getter 和 setter函数(optional)

在读取访问器属性时,会调用 getter函数,这个函数负责返回有效的值;在写入访问器属性时,会调用setter 函数并传入新值,这个函数负责决定如何处理数据。

也就是说不需要显示的调用set和get函数,它是自动执行的。

  • 只指定 getter 意味着属性是不能写
  • 只指定 setter 函数的属性也不能读,否则在非严格模式下会返回 undefined,
var book = {
    _year: 2004, //这个属性表示只能通过对象(object)访问
};
// 这里访问器属性是year,_year是数据属性
Object.defineProperty(book, "year", {
    get: function(){
        return this._year;
    },
    set: function(newYear){
        this._year=newYear;
    }
});
book.year = 2005;
console.info(book._year);  //2005

查看属性的信息:

     Object.getOwnPropertyDescriptor(book,"_year")

2. 创建对象的方法

2.1 使用Object方式创建

2.1.1 new

使用 new 操作符后跟 Object 构造函数

    var p1 = new Object();
    p1.name="p1";
2.1.2 对象字面量
    var p2 = {
        name:"p2"
    };

虽然 Object 构造函数或对象字面量都可以用来创建单个对象,但这些方式有个明显的缺点: 使用同一个接口创建对象时会产生大量代码


2.2. 更有效的创建对象的方法

2.2.1. 工厂模式

用函数来封装以特定接口创建对象的细节

function createPerson(name, age, job){
    var o = new Object();
    o.name = name;
}
var person1 = createPerson("Nicholas");
2.2.2. 构造函数模式

ECMAScript 中的构造函数可用来创建特定类型的对象。像 Object 和 Array 这样
原生构造函数,在运行时会自动出现在执行环境中。此外,也可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。

function Person(name) {
    this.name = name;
};
var person1 = new Person("Nicholas");
var person2 = new Person("Nicholas");
// 这两个对象都有一个 constructor(构造函数)属性,该属性指向 Person

要创建 Person 的新实例,必须使用 new 操作符。以这种方式调用构造函数实际上会经历以下 4个步骤:
(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
(3) 执行构造函数中的代码(为这个新对象添加属性);
(4) 返回新对象。

console.info(person1.constructor == person2.constructor); //t
console.info(person1.constructor == Person); //t
console.info(person1 instanceof Person); //t
console.info(person1 instanceof Object);  //t

构造函数的三个特点:

  • 没有显式地创建对象;
  • 直接将属性和方法赋给了 this 对象;
  • 没有 return 语句。

只要用new调用的就是构造函数,不用new的就不是。

// 当作构造函数使用
var person = new Person("Nicholas", 29, "Software Engineer");
person.sayName(); //"Nicholas"

// 作为普通函数调用
Person("Greg", 27, "Doctor"); // 添加到 window
window.sayName(); //"Greg"

// 在另一个对象的作用域中调用
var o = new Object();
Person.call(o, "Kristen", 25, "Nurse");
o.sayName(); //"Kristen"
2.2.3. 原型模式

无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype属性,这个属性指向函数的原型对象
在默认情况下,所有原型对象都会自动获得一个 constructor(构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针

function Person(name) {
    this.name = name;
};
// 函数自带了prototype属性
// 这个属性指向 系统为这个函数自动创建的 “原型对象” Person Prototype
console.info(Person.prototype);  //Person {}
// “原型对象”里面有一个属性 叫做constructor  这个属性指向 这个函数
console.info(Person.prototype.constructor); //[Function: Person]

当用构造函数创建一个新实例后,该实例的内部会包含一个指针,指向刚才的那个“原型对象”,这个指针叫[[prototype]], 使用__proto__ 访问。
也就是说, 每个实例只是指向了“原型对象”,而不与它们的构造函产生直接的联系。
实例的指针 -> 原型对象 -> 原型对象的指针 -> 构造函数

function Person(){
}

Person.prototype.name = "Nicholas";
var p1=new Person();
console.info(Person.prototype); //Person { name: 'Nicholas' }
console.info(p1.__proto__); //Person { name: 'Nicholas' }
console.info(Person.prototype.constructor); //[Function: Person]
2.2.4. 组合使用构造函数模式和原型模式
  • 构造函数模式用于定义实例属性
  • 原型模式用于定义方法和共享的属性

每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度地节省了内存。

function Person(name) {
    this.name = name;
    this.friends = ["Shelby", "Court"];
}

// typeof(Person.prototype)  object
Person.prototype = {
    constructor: Person,
    sayName: function () {
        alert(this.name);
    }
}
var person1 = new Person("Nicholas");
var person2 = new Person("Greg");
person1.friends.push("Van");
alert(person1.friends);//"Shelby,Count,Van"
alert(person2.friends);//"Shelby,Count"
alert(person1.friends === person2.friends);//false
alert(person1.sayName === person2.sayName);//true
2.2.5. 动态原型模式

这里只在 sayName()方法不存在的情况下,才会将它添加到原型中。

function Person(name) {
    this.name = name;
    this.friends = ["Shelby", "Court"];
    if (typeof this.sayName != "function"){
        Person.prototype.sayName = function(){
            alert(this.name);
        }
    }
}
2.2.6. 寄生构造函数模式

除了使用构造函数的方法初始化对象以外,这个方法和工厂模式是一样的。

function Person(name) {
    var o = new Object();
    o.name = name;
    o.sayName = function () {
        alert(this.name);
    };
    return o;
}
var friend = new Person("Nicholas");
friend.sayName(); //"Nicholas"
2.2.7. 稳妥构造函数模式
  • 不用 this
  • 不用 new
function Person(name, age, job) {
    //创建要返回的对象
    var o = new Object();
    o.sayName = function () {
        alert(name);
    };

    //返回对象
    return o;
}

var friend = Person("Nicholas", 29, "Software Engineer");

// name只能通过sayname来访问
friend.sayName(); //"Nicholas"

一些变量只能通过函数访问,确保安全性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值