js的this和面向对象编程
很奇怪的是很多书或资料没有把这个事情讲清楚。
关键就是在于没有一个整体的思维技术模式,问题被隔离了所以反而不容易理解。
我们先看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和面向对象编程的更多相关文章
- JS - ES5与ES6面向对象编程
1.面向对象 1.1 两大编程思想 1.2 面向过程编程 POP(Process-oriented programming) 1.3 面向对象编程 OOP (Object Oriented Progr ...
- JS 学习笔记 (七) 面向对象编程OOP
1.前言 创建对象有很多种方法,最常见的是字面量创建和new Object()创建.但是在需要创建多个相同结构的对象时,这两种方法就不太方便了. 如:创建多个学生信息的对象 let tom = { n ...
- JS面向对象编程(一):封装
js是一门基于面向对象编程的语言. 如果我们要把(属性)和(方法)封装成一个对象,甚至要从原型对象生成一个实例,我们应该怎么做呢? 一.生成对象的原始模式 假定把猫看 ...
- 快速理解JavaScript面向对象编程—原型
总的来说js语言就是门面向对象编程的语言,对象这个概念几乎贯穿了整个js的学习. 对象 创建对象两种方法:(若要生成对象实例必须调用构造函数) 1.var obj = {name:"jer& ...
- 带你一分钟理解闭包--js面向对象编程
上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...
- Js面向对象编程
Js面向对象编程 1. 什么是面向对象编程? 我也不说不清楚什么是面向对象,反正就那么回事吧. 编程有时候是一件很快乐的事,写一些小游戏,用编程的方式玩游戏等等 2. Js如何定义一个 ...
- js原生设计模式——3简单工厂模式\js面向对象编程实例
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- JS面向对象编程(进阶理解)
JS 面向对象编程 如何创建JS对象 JSON语法声明对象(直接量声明对象) var obj = {}; 使用 Object 创建对象 var obj = new Object(); JS对象可以后期 ...
- JavaScript--我发现,原来你是这样的JS:面向对象编程OOP[2]--(创建你的那个对象吧)
一.介绍 我们继续面向对象吧,这次是面向对象编程的第二篇,主要是讲创建对象的模式,希望大家能从博客中学到东西. 时间过得很快,还是不断的学习吧,为了自己的目标. 二.创建对象 1.前面的创建对象方式 ...
随机推荐
- [Android]官网《UI/Application Exerciser Monkey》中文翻译
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5049041.html 翻译自 Android Develope ...
- Java Web中乱码问题
response.setContentType("text/html;charset=UTF-8"); 用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式.什么编码读取这个 ...
- Android Gson的使用总结
1.概念 Gson是谷歌发布的一个json解析框架 2.如何获取 github:https://github.com/google/gson android studio使用 compile 'com ...
- JAVA匿名内部类
首先定义一个抽象类Computer public abstract class Computer { //抽象类是不可以常见对象的 int a=1; public abstract void onli ...
- iOS--UICollectionView(滚动视图)入门
UICollectionView @interface UICollectionView : UIScrollView UICollectionView 和UICollectionViewCon ...
- android 传感器应用
本章讲述Android开发中,传感器应用相关的知识点. 1.功能需求 做一个基于传感器的水平尺应用. 2.软件实现
- ionic 使用sqlite
昨天被ionic和sqlite折腾一天,怎么也无法实现读取,后来才发现,原来是codova中的sqliteplugin版本问题. 问题:Database location or iosDatabase ...
- parawork功能使用说明
项目整体估算 1.项目估算:依据项目属性,开发规模,参考行业平均生存率自动估算软件工作量.成本.工期 : 2.项目生产率分析:掌握研发生产率行业水平,方便项目管理 : 3.工期占比分析:了解项目关键节 ...
- JDBC Driver Types
JDBC Driver Types Type1: JDBC-ODBC Bridge Driver Type2: JDBC-Native API Type3: JDBC-Net Pure Java Ty ...
- 关于Thinkcmf中热门文章的使用
今天在做一个首页新闻列表页面的功能时候,因为要读取大量的新闻内容列表.如果每条数据都要从数据按照文章id和term_id来对应取值,无疑是很痛苦的. 然而机智如我,发现cmf框架中热门文章的用法: 在 ...