当前位置: 首页 > news >正文

js面向对象:创建对象的几种方式

1、普通模式

//var person new Object();(new Object 用{}代替)

var person = {};
person.name = 'dd';
person.color = 'red';
person.sayHi = function(){
 alert(this.name);// this.name等价于 person.name
};
调用:直接用person.name、person.sayHi()
缺点:相似的对象需多次创建,产生大量的重复代码
 
2、工厂模式
function createPerson(name, color) {
    var person = {};
    person.name = name;
    person.color = color;
    person.sayHi = function() {
        alert(this.name);
    }
    return person;
}
调用:var person1 = createPerson(‘zhangsna’, ‘red’);
person1.name; 、 person1.sayHi();
优点:函数createPerson()能够根据接受的参数来构建一个包含所有必要信息的person对象,可以无数次地调用这个函数,每次都会返回一个包含三个属性、一个方法的对象。在创建多个相似对象时,就可省去重复代码
缺点:没有解决对象识别的问题(即不知道对象的类型)
 

3、构造函数模式

function Person(name, color) {
    this.name = 'dd';
    this.color = 'red';
    this.sayHi = function() {
        alert(this.name);
    }
}
 
调用:var person  = new Person();new命令本身就可以执行构造函数,所以后面的构造函数可以带括号,也可以不带括号var person  = new Person
优点:可以创建自定义的构造函数,定义自定义对象类型的属性和方法。
缺点:每个方法都要在每个实例上重复创建一遍,
说明:构造函数也是函数,与其他函数唯一的区别就在于调用它们的方式不同,任何函数通过new操作符来调用就可作为构造函数。
如果忘了使用new命令,直接调用构造函数,构造函数就变成了普通函数,并不会生成实例对象。
为了保证构造函数必须与new命令一起使用,一个解决办法是,在构造函数内部使用严格模式,即第一行加上“use strict”。
function Fubar (foo, bar) {
  "use strict"
  this._foo = foo;
  this._bar = bar;
}
 
Fubar();
// TypeError: foo is undefined
 
上面代码的Fubar为构造函数,use strict命令保证了该函数在严格模式下运行。由于在严格模式中,函数内部的this不能指向全局对象,默认等于undefined,导致不加new调用会报错(JavaScript不允许对undefined添加属性)。
 
另一个解决办法,是在构造函数内部判断是否使用new命令,如果发现没有使用,则直接返回一个实例对象。
function Fubar (foo, bar) {
  if (!(this instanceof Fubar)) {
    return new Fubar(foo, bar);
  } 
  this._foo = foo;
  this._bar = bar;
}
instanceof运算符用来确定一个对象是否为某个构造函数的实例(用来判断对象的类型)
""instanceofString   //无效
 
1   instanceofNumber   //无效
 

4、 原型模式

         function Person() {

}

Person.prototype  =  {

name : ‘dd’,

color 'red',
    sayHi :function() {
       alert(this.name);
    }

}
优点:每个函数都有一个prototype属性(原型属性),这个属性是一个指针,指向一个对象(原型对象),原型对象中的属性和方法是所有函数实例共享的

 

给原型对象添加属性和方法:

1)Person.prototype  =  {

name : ‘dd’,

color 'red',
    sayHi:function() {
       alert(this.name);
             }

}

2)

Person. prototype.name = ‘dd’;

Person. prototype.color = ‘red’;

Person. prototype.say Hi = function(){

 

};

调用: var person = new Person();

person.name 、person.sayHi();

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

当调用构造函数创建一个新实例后,该实例的内部包含一个指针(内部属性_proto_),指向构造函数的原型属性

 

缺点:当原型中的属性出现引用类型值的时候,就会出现如下问题:

function Person() {

}

Person.prototype  =  {

name : ‘dd’,

color 'red',

friends:[‘Shelby’, ’Court’],
    say:function() {
       alert(this.name);
    }

}

var person1 = new Person();

var person2 = new Person();

person1.friends.push(‘Van’);
alert(person1.friends); //输出 “Shelby, Court, Van”

alert(person2.friends); //输出 “Shelby, Court, Van”

person1.name = 'ddd';
alert(person1.name);//输出 ddd
alert(person2.name);//输出 dd

如果是基本类型的话实例person1的name会调用自己实例中设置的属性,person2则还是运用原型中的name属性。

由于friends数组存在于Person.prototype而非person1中,所以person1.friends与person2.friends指向与同一个数组,这样的结果并不是我们想要的,此情况下可以采用构造函数模式与原型模式相结合,构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。

function Person(name, color) {
    this.name = name;
    this.color = color;
    this.friends = ['Shelby', 'Court'];
}
Person.prototype = {
    sayHi : function() {
        return this.name;
    }
}
var person1 = new Person('a', 'red');
var person2 = new Person('b', 'red');
person1.friends.push('Van');
alert(person1.friends); //输出 “Shelby, Court, Van”
alert(person2.friends); //输出 “Shelby, Court”

 

原型链:(基本思想就是利用原型让一个引用类型继承另一个引用类型的属性和方法)

function SuperType() {
    this.superName = "a";
}
SuperType.prototype.getSuperName = function() {
    return this.superName;
}
function SubType() {
    this.subName = "b";
}
SubType.prototype = new SuperType();
SubType.prototype.getSubName = function(){
    return this.getSubName();
}
var subType = new SubType();
console.log(subType.getSuperName());

 

 

当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止,到查找到达原型链的顶部 - 也就是 Object.prototype - 但是仍然没有找到指定的属性,就会返回 undefined,例子:

    function foo() {
            this.add = function (x, y) {
                return x + y;
            }
        }

        foo.prototype.add = function (x, y) {
            return x + y + 10;
        }

        Object.prototype.subtract = function (x, y) {
            return x - y;
        }

        var f = new foo();
        alert(f.add(1, 2)); //结果是3,而不是13
        alert(f.subtract(1, 2)); //结果是-1

我们可以赋值任何类型的对象到原型上,但是不能赋值原子类型的值,比如如下代码是无效的

function Foo() {}
Foo.prototype = 1; // 无效
 

hasOwnProperty是Object.prototype的一个方法,他能判断一个对象是否包含自定义属性而不是原型链上的属性,因为hasOwnProperty 是 JavaScript 中唯一一个处理属性但是不查找原型链的函数。

// 修改Object.prototype
Object.prototype.bar = 1;
var foo = {goo: undefined};
console.log(foo.bar); // 1
console.log('bar' in foo); // true

console.log(foo.hasOwnProperty('bar')); // false
console.log(foo.hasOwnProperty('goo')); // true
 

同时在使用 for in loop 遍历对象时,推荐总是使用 hasOwnProperty 方法,这将会避免原型对象扩展带来的干扰

Object.prototype.bar = 1;

var foo = {moo: 2};
for(var i in foo) {
    console.log(i); // 输出两个属性:bar 和 moo
}

我们没办法改变for in语句的行为,所以想过滤结果就只能使用hasOwnProperty 方法,代码如下:

// foo 变量是上例中的
for(var i in foo) {
    if (foo.hasOwnProperty(i)) {
        console.log(i);
    }
}

由于我们使用了 hasOwnProperty,所以这次只输出 moo。如果不使用 hasOwnProperty,则这段代码在原生对象原型(比如 Object.prototype)被扩展时可能会出错。

推荐使用 hasOwnProperty

注:此文章是同事所给资料复制过来的

转载于:https://www.cnblogs.com/mandy-dyf/articles/4539076.html

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 正确理解ThreadLocal(转)
  • 软件工程课程总结
  • HDU 1166 敌兵布阵 (线段树)
  • gps相关
  • ibatis.net的一些映射文件语法
  • Channel SDK (渠道SDK) for Unity
  • OpenResty(Nginx)+Lua+GraphicsMagick实现缩略图功能
  • Python模块之urllib
  • MyEclipse8.6配置Maven
  • Nginx和PHP-FPM的启动/重启脚本 [转发]
  • Java知多少(88)列表和组合框
  • Dev之GridControl详解
  • linux 安装pnp时出现了一些错误
  • 报表打印网络按比例打印网络图片
  • Nim教程【十一】
  • 网络传输文件的问题
  • SegmentFault for Android 3.0 发布
  • django开发-定时任务的使用
  • ECS应用管理最佳实践
  • extract-text-webpack-plugin用法
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • laravel5.5 视图共享数据
  • markdown编辑器简评
  • Node项目之评分系统(二)- 数据库设计
  • Python 基础起步 (十) 什么叫函数?
  • Ruby 2.x 源代码分析:扩展 概述
  • Solarized Scheme
  • thinkphp5.1 easywechat4 微信第三方开放平台
  • ubuntu 下nginx安装 并支持https协议
  • Vue官网教程学习过程中值得记录的一些事情
  • Vue小说阅读器(仿追书神器)
  • 程序员最讨厌的9句话,你可有补充?
  • 好的网址,关于.net 4.0 ,vs 2010
  • 两列自适应布局方案整理
  • 数据仓库的几种建模方法
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 终端用户监控:真实用户监控还是模拟监控?
  • 1.Ext JS 建立web开发工程
  • HanLP分词命名实体提取详解
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • ​LeetCode解法汇总518. 零钱兑换 II
  • #HarmonyOS:基础语法
  • (3)STL算法之搜索
  • (Python) SOAP Web Service (HTTP POST)
  • (笔试题)合法字符串
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (转)为C# Windows服务添加安装程序
  • (最新)华为 2024 届秋招-硬件技术工程师-单板硬件开发—机试题—(共12套)(每套四十题)
  • ******IT公司面试题汇总+优秀技术博客汇总
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil