Javascript创建对象几种方法解析

Javascript面向对象编程一直是面试中的重点,将自己的理解整理如下,主要参考《Javascript高级程序设计 第三版》,欢迎批评指正。

通过字面量形式,创建对象:

        var person_1 = {
name: "userName",
age: 20
}

工厂模式创建对象

    通过一个构造函数接收参数的方式构造对象,可无数次调用这个函数,通过改变参数构造不同的对象
         function createPerson(name,age){
var o = new Object();//创建一个空的对象 -- 原料 o.name = name;
o.age = age;
o.sayName = function(){ //给对象属性赋值 -- 加工过程
alert(this.name)
} return o; //返回加工后的对象 -- 出厂
}
var leo = createPerson('Leo',30);
leo.sayName(); //"Leo"
var cherry = createPerson('Cherry',20);
cherry.sayName(); //"Cherry"
    缺点:工厂模式创建的对象,无法判断其类型

构造函数模式:

    类似Array,Object这种原生的构造函数,我们可以通过创建自定义的构造函数,从而定义自定义对象的类型和方法
        function Person(name,age){
this.name = name;
this.age = age;
this.sayName = function(){
alert(this.name);
}
}
var leo = new Person('Leo',18);
var cherry = new Person('Cherry',25);
leo.sayName();
cherry.sayName();
  1. 与工厂模式对比,几点不同:没有现实的创建空对象;直接将属性和方法赋值给this;不需要return
  2. 通过New操作符创建Person对象的新实例:①创建一个新的对象 ②this指向这个新对象(作用域)③执行构造函数中的代码,对新对象添加属性和方法④返回新对象
  3. 通过instanceof检测对象类型,发现通过Person构造函数创建的对象,即使Person类的实例,又是Object对象的实例 - 创建自定义的构造函数表明可以将它的实例标识为一种特定的类型
        alert(leo instanceof Person); //true
alert(leo instanceof Object); //true 所有对象都继承自Object
  1. 区分构造函数和普通函数

    ①. 任何函数通过new操作符调用,就可做为构造函数

    ②. 自定义的构造函数,不通过new调用,与普通函数没有区别
        Person('window',100);//直接调用,相当于将Person类的属性方法直接添加到了this上
window.sayName(); //window
  1. 缺点:通过构造函数,每个方法都要在实例上重新创建一遍,每个实例的sayName方法,相当于执行this.sayName = new Function("alert(this.name)")单独创建出来的
        alert(leo.sayName==cherry.sayName);//false

原型模式:

  1. 创建的每个函数都有prototype属性,这个属性指向一个其属性和方法由某个特定类的所有实例共享的对象,利用prototype,我们就可将定义对象实例的信息放在原型对象中,不必在构造函数中定义。
        function Person(){} //构造函数变成空
Person.prototype.name = 'Leo';
Person.prototype.age =30;
Person.prototype.sayName = function(){
alert(this.name);
}
var person1 = new Person();
var person2 = new Person();
alert(person1.sayName==person2.sayName);//true 将sayName方法定义在Person的prototype属性中,可由多个不同的实例共享
//简化写法:
function Person() { } //构造函数变成空
Person.prototype = {
name: 'Leo',
age: 30,
sayName: function () {
alert(this.name);
}
}
var person1 = new Person();
var person2 = new Person();
  1. 只要创建一个新函数,就会为该函数创建一个prototype属性,这个属性指向原型对象。在我们创建的对象person1和person2中都包含一个内部属性,该属性指向Person.prototype,因此两个实例都可以调用原型中的sayName()方法。Object.getPrototypeOf()方法可以更方便的取得一个对象的原型.
      alert(Person.prototype.isPrototypeOf(person1));//true
alert(Person.prototype.isPrototypeOf(person2));//true
alert(Object.getPrototypeOf(person1)==Object.getPrototypeOf(person2));//true
  1. 给一个对象添加一个属性,这个属性会屏蔽原型对象中存储的同名属性,通过hasOwnProperty()方法可判断是实例对象中的属性,还是原型中的属性;通过in运算符,可以判断在对象上能否找到某属性,而不区分是实例属性还是原型属性,for in循环中只会遍历可访问、可枚举的属性。
        person1.name='Nancy';
alert(person1.name);//Nancy
alert(person1.hasOwnProperty("name"));//True 实例对象上的属性
alert(person2.hasOwnProperty("name"));//false 原型中的属性
alert("name" in person1);//true
alert("name" in person2);//true
for(key in person1){
alert(`${key}:${person1[key]}`)
}
  1. 原型模式的缺点:①缺少向构造函数传递初始化参数这一环节,使得同一个对象的所有实例在默认情况下都会取得相同的属性值。②在实例中修改引用属性的值,会影响其他的实例。
        function Newperson(){
} Newperson.prototype = {
constructor : Newperson,
name:"Tony",
age:30,
job:"Developer",
friends:['Leo','Cherry'],
sayName:function(){
alert(this.name);
}
} let newPerson1 = new Newperson();
let newPerson2 = new Newperson();
alert(newPerson1.friends);//Leo, Cherry
alert(newPerson2.friends);//Leo, Cherry
newPerson1.friends.push('Mai');//friends属性引用数组在Newperson.prototype而非newPerson1中,newPerson1.friends和newPerson2.friends指向的是同一个引用
alert(newPerson1.friends);//Leo, Cherry, Mai
alert(newPerson2.friends);//Leo, Cherry, Mai
alert(newPerson1.friends === newPerson2.friends);//true

组合使用构造函数模式和原型模式

  1. 组合使用构造函数模式和原型模式是创建自定义类型的常见方式,构造函数用于定义实例属性,原型模式用于定义方法和共享属性。
      function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Leo","Cherry"];
} Person.prototype = {
constructor:Person,
sayName:function(){
alert(`${this.name} is a ${this.job}.`);//公共方法
}
} let person1 = new Person('Mai',18,'actor');
let person2 = new Person('Bob',25,'developer');
person1.sayName();
person2.sayName();
alert(person1.friends == person2.friends);//false friends属性在构造函数中定义,不在原型中,两个实例不会相互影响
person1.friends.push('Tony');
person2.friends.push('Melody');
alert(person1.friends);//Leo, Cherry, Tony
alert(person2.friends);//Leo, Cherry, Melody

Javascript创建对象几种方法解析的更多相关文章

  1. 创建JAVASCRIPT对象3种方法

    创建JAVASCRIPT对象3种方法 方法一:直接定义并创建对象实例 var obj = new Object();    //创建对象实例 //添加属性obj.num = 5;   //添加属性 o ...

  2. ASP.NET,C#后台调用前台javascript的五种方法

    C#后台调用前台javascript的五种方法 由于项目需要,用到其他项目组用VC开发的组件,在web后台代码无法访问这个组件,所以只好通过后台调用前台的javascript,从而操作这个组件.在网上 ...

  3. VC调用javascript的几种方法

    第一种:通过execScript调用.这种方法,虽然操作方便,但不能获取返回值.m_spHtmlDoc->get_parentWindow(&m_pHtmlWindow);VARIANT ...

  4. Java/JSP获得客户端网卡MAC地址的三种方法解析

    java/jsp获得客户端(IE)网卡MAC地址的方法大概有三种. 1.通过命令方式,在客户端执行Ipconfig 等等.(java/jsp) 2.通过ActiveX的方法.(jsp) 3.通过向13 ...

  5. C#后台调用前台javascript的五种方法小结

    第一种,OnClientClick (vs2003不支持这个方法) <asp:Button ID="Button1" runat="server" Tex ...

  6. 【转】 C#后台调用前台javascript的五种方法

    第一种,OnClientClick    (vs2003不支持这个方法)<asp:ButtonID="Button1" runat="server" Te ...

  7. 四种方法解析JSON数据

    (1)使用TouchJSon解析方法:(需导入包:#import "TouchJson/JSON/CJSONDeserializer.h") //使用TouchJson来解析北京的 ...

  8. JAVA 创建对象4种方法

    java创建对象的几种方式 博客分类: java   (1) 用new语句创建对象,这是最常见的创建对象的方法.(2) 运用反射手段,调用java.lang.Class或者java.lang.refl ...

  9. 网页中插入javascript的几种方法

    网页中插入javascript的方法常见的有两种: 一.直接使用html标记 JavaScript 可以出现在 html的任意地方.使用标记<script>…</script> ...

随机推荐

  1. poj 3321(带时间戳 + 区间统计)

    题目描述: 给定一颗树,求某个节点的子树的val值之和 可以用树的前序遍历给每一个节点编号,从而可以确定一个节点的子树的范围,这样就可以进行直接在区间上进行统计了. vector < int & ...

  2. C++实现斐波那契第N项非递归与递归实现的时间比较

    /* * 斐波那契数列.cpp * * Created on: 2018年4月9日 * Author: soyo */ #include<iostream> #include<cti ...

  3. bzoj 2733: [HNOI2012]永无乡【并查集+权值线段树】

    bzoj上数组开大会T-- 本来想用set瞎搞的,想了想发现不行 总之就是并查集,每个点开一个动态开点的权值线段树,然后合并的时候把值并在根上,询问的时候找出在根的线段树里找出k小值,看看这个值属于哪 ...

  4. Tensor Operation

    Main operation categories that encompass the operations of tensors. Reshaping operations Element-wis ...

  5. 第四代增强 NEW BADI的定义及实现

    NEW BADI 是在第四代增强框架下创建的BADI,是相对于第三代增强Classic Badi 而言的. 根据第四代增强的基本概念,所有显式增强Enhancement options 都必须放在增强 ...

  6. 我的ubuntu连vi都没有??那在命令行怎么编辑文件??

    今天弄了个docker下的ubuntu官方镜像,想在镜像里做一点实验,免得把自己的环境写得乱七八糟. 把代码文件mount进去之后,开始编译,但是镜像太干净了,什么工具都没有,于是先装cmake ap ...

  7. [SDOI2016]墙上的句子

    题目描述 考古学家发现了一堵写有未知语言的白色墙壁,上面有一个n行m列的格子,其中有些格子内被填入了某个A至Z的大写字母,还有些格子是空白的. 一直横着或竖着的连续若干个字母会形成一个单词,且每一行的 ...

  8. 2017 JUST Programming Contest 3.0 E. The Architect Omar

    E. The Architect Omar time limit per test 1.0 s memory limit per test 256 MB input standard input ou ...

  9. 题解报告:hdu 1159 Common Subsequence(最长公共子序列LCS)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1159 Problem Description 给定序列的子序列是给定的序列,其中有一些元素(可能没有) ...

  10. NSoup获取网页源代码

    NSoup是JSoup的Net移植版本.使用方法基本一致. 如果项目涉及HTML的处理,强烈推荐NSoup,毕竟字符串截断太苦逼了. 下载地址:http://nsoup.codeplex.com/ # ...