很奇怪的是很多书或资料没有把这个事情讲清楚。

关键就是在于没有一个整体的思维技术模式,问题被隔离了所以反而不容易理解。

我们先看this,这是js的关键字,指示函数的上下文对象。

这里问题就来了,比如:

            var obj = {};

            obj.name = 'test';

            obj.output = function () {

                console.log(this.name);

            };

            obj.output();

  this指定了上下文对象,当然如果没有指定就会指定到全局变量,window,这就是问题的根源所在。所以最好的解决方案,就是使用'use strict'严格模式,一但出错,比较容易定位问题。

在不用严格模式下,我们看看问题出现在哪里?

重命名变量时:

比如上面,console.log(obj.name),不用this的话,那么在其它代码里obj被另外变量定义,明显要出错。但用了this,代码环境一变就出问题。

比如我们把这个对象重构成构造函数:

function Obj(name) {

....

都要使用this关键字。

但是构造函数也是个函数,稍不注意就会当成普通函数调用。不加new,变成这样。

Obj('test')...

这时构造函数被错误运行,而它竟争不会出错,为什么呢?在非严格模式下,构造函数的this指向了全局的window,这就是JS最大的缺陷。不仅不能得到正确的运行结果,还污染了全局。在大量的JS里,误调用一个构造函数就是灾难性的结果。

为什么面向对象的程序比如C#,Java不会有这个问题?因为它们使用class关键字,class在定义阶段无法使用(除非明确定义的static属性和方法)

可见,JS的这个严重的this,不仅是全局变量的问题,还影响了整个构造函数的面向对方方式编程,所以安全的方式写构造函数是必须的,就是不用new,也能构造。

当然'use strict'只是治标。治本就是要让new 和不new都得到一致的结果。

JS的构造函数,如果直接运行,那么返回结果就是对象,this定义的对象被抛弃,很特别的一点。所以干脆就不用定义this用new,直接使用返回对象。

            function pClass() {
this.Name = 'test';
this.output = function () {
console.log(this.Name);
}
return new pClass();
} var p1 = pClass();
var p2 = new pClass();
p1.output();
p2.output();

  不用new,倒是对了,第一个问题得到解决,但如果再new就会变成嵌套调用。出错。很明显,出错是因为this,所以我们在内部,直接定义对象返回,做成真正的“构造函数”

            function pClass() {

                return {
Name: 'test',
output: function () {
console.log(this.Name);
}
}
} var p1 = pClass();
var p2 = new pClass();
p1.output();
p2.output();

  这问题又来了,直接返回对象避免了this的问题,但明显重复,比如p1,p2使用了两个实例的output方法,这是不可以容忍的。

所以这就导致了JS在处理对象的创建方面无法提供有效的机制,this和new不匹配,彻底的解决方案就是ES6,引入class关键字,否则的话,不管怎么创建都没有完美的解决方案,而且代码啰嗦。

在ES5上,次好的解决方案是:

1.引入'use strict',防止错误的构造函数及this

2.构造函数首字母大写,其它的一律驼峰,通过命名来区分

3.创建对象一律使用new,并使用简单的prototype模式

4.非new形式尽量使用module模式

5.最关键的地方,JS对象就不是长项,面向对象编程也并非最佳方式,应该优先考虑组合模式,把对象和方法体分开,这从根源上解决JS的对象弱点。

js的this和面向对象编程的更多相关文章

  1. JS - ES5与ES6面向对象编程

    1.面向对象 1.1 两大编程思想 1.2 面向过程编程 POP(Process-oriented programming) 1.3 面向对象编程 OOP (Object Oriented Progr ...

  2. JS 学习笔记 (七) 面向对象编程OOP

    1.前言 创建对象有很多种方法,最常见的是字面量创建和new Object()创建.但是在需要创建多个相同结构的对象时,这两种方法就不太方便了. 如:创建多个学生信息的对象 let tom = { n ...

  3. JS面向对象编程(一):封装

    js是一门基于面向对象编程的语言.      如果我们要把(属性)和(方法)封装成一个对象,甚至要从原型对象生成一个实例,我们应该怎么做呢?  一.生成对象的原始模式            假定把猫看 ...

  4. 快速理解JavaScript面向对象编程—原型

    总的来说js语言就是门面向对象编程的语言,对象这个概念几乎贯穿了整个js的学习. 对象 创建对象两种方法:(若要生成对象实例必须调用构造函数) 1.var obj = {name:"jer& ...

  5. 带你一分钟理解闭包--js面向对象编程

    上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...

  6. Js面向对象编程

    Js面向对象编程 1.     什么是面向对象编程? 我也不说不清楚什么是面向对象,反正就那么回事吧. 编程有时候是一件很快乐的事,写一些小游戏,用编程的方式玩游戏等等 2.     Js如何定义一个 ...

  7. js原生设计模式——3简单工厂模式\js面向对象编程实例

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  8. JS面向对象编程(进阶理解)

    JS 面向对象编程 如何创建JS对象 JSON语法声明对象(直接量声明对象) var obj = {}; 使用 Object 创建对象 var obj = new Object(); JS对象可以后期 ...

  9. JavaScript--我发现,原来你是这样的JS:面向对象编程OOP[2]--(创建你的那个对象吧)

    一.介绍 我们继续面向对象吧,这次是面向对象编程的第二篇,主要是讲创建对象的模式,希望大家能从博客中学到东西. 时间过得很快,还是不断的学习吧,为了自己的目标. 二.创建对象 1.前面的创建对象方式 ...

随机推荐

  1. Vue.js 递归组件实现树形菜单

    最近看了 Vue.js 的递归组件,实现了一个最基本的树形菜单. 项目结构: main.js 作为入口,很简单: import Vue from 'vue' Vue.config.debug = tr ...

  2. eclipse — Failed to load the JNI shared library”……\jvm.dll问题原因以及解决方案

    首先上一张出现问题的图片: 出现这个问题一般是你的jdk和eclipse不是同一位的,比如你的jdk是32位的但是eclipse下载的是64位的就会导致这种问题. 解决方案:把两者都换为32或者64位 ...

  3. MySQL单表百万数据记录分页性能优化

    背景: 自己的一个网站,由于单表的数据记录高达了一百万条,造成数据访问很慢,Google分析的后台经常报告超时,尤其是页码大的页面更是慢的不行. 测试环境: 先让我们熟悉下基本的sql语句,来查看下我 ...

  4. 我的Android第五章:通过Intent实现活动与活动之间的交互

    Intent在活动的操作 作用: Itent是Android程序中各个组件直接交换的一个重要方式可以指定当前组件要执行任务同时也可以给各个组件直接进行数据交互              同时Inten ...

  5. 使用VS2015开发跨平台APP

      VS2013开始就可以基于HTML5开发WEBAPP,并借助xamarin或者PHONEGAP实现原生APP 不过升级麻烦,直接下载VS2015CTP6,最好安装在同一个分区上,ANDROID S ...

  6. 移动端rem布局实践

      一.rem 适配基本概念: 对于移动端的开发,rem 适配必不可少,我们可以用多种方式实现, 根据 html 的 fontSize 属性值为基准,其它所有的 rem 值,根据这个基准计算.我们根据 ...

  7. ORACLE查看SQL的执行次数/频率

    在ORACLE数据库应用调优中,一个SQL的执行次数/频率也是常常需要关注的,因为某个SQL执行太频繁,要么是由于应用设计有缺陷,需要在业务逻辑上做出优化处理,要么是业务特殊性所导致.如果执行频繁的S ...

  8. [AlwaysOn Availability Groups]排查:AG超过RPO

    排查:AG超过RPO 在异步提交的secondary上执行了切换,你可能会发现数据的丢失大于RPO,或者在计算可以忍受的数据都是超过了RPO. 1.通常原因 1.网络延迟太高,网络吞吐量太低,导致Pr ...

  9. apache+mysql+php的环境配置

    一 配置前的准备 1 先设置环境变量(win7的) win10 二 配置apache 我用EditPlus打开httpd.conf LoadModule php5_module  "c:/w ...

  10. Hive官方手册翻译(Getting Started)

    翻译Hive官方文档系列,文中括号中包含 注: 字样的,为我自行标注的,水平有限,翻译不是完美无缺的.如有疑问,请参照Hive官方文档对照查看.   内容列表 Cloudera制作的Hive介绍视频 ...