前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >避免这些常见的JavaScript错误

避免这些常见的JavaScript错误

作者头像
疯狂的技术宅
发布2019-03-28 10:48:05
6290
发布2019-03-28 10:48:05
举报
文章被收录于专栏:京程一灯

在今天,JavaScript是最流行的编程语言之一,如果你希望钻研JavaScript,这里有几个需要避免的问题

1.使用==而不是===

在刚开始学习JavaScript时,这是初学者最容易犯的错误。==会将类型转换,而===却不会。

代码语言:javascript
复制
// ==的例子1 == "1" // true"/t" == 0 // true"34" == 2 // falsenew Number(10) == 10 // trueNumber(10) === 10 //true//  ===的例子1 === "1" // false"/t" === 0 // false"34" === 2 // false10 === 10 //true// where things get wierd....Number(10) === 10 //truenew Number(10) === 10 //false, LHS will actually be an object!

通常,应该使用严格相等操作符===,这样具有可预测性,查找bug时候不会出现不必要的问题。

2.使用typeof

如果变量被定义了,你应该只使用typeof去检查,否则,会出现不一致的行为。

代码语言:javascript
复制
console.log(typeof "foo" === "string"); //true console.log(typeof String("foo") === "string"); // trueconsole.log(typeof new String("foo") === "string"); // false,因为new操作产生的都是对象。console.log(typeof 1.2 === "number"); //trueconsole.log(typeof new Date() === "Date"); //false ,Date是对象console.log(typeof [1,2,3] === "array"); //false, 数组也是对象/** 正确检测对象类型方法 **/function is(type, obj) {    var clas = Object.prototype.toString.call(obj).slice(8, -1);    return obj !== undefined && obj !== null && clas === type;}console.log(is('String', 'test')); // trueconsole.log(is('String', new String('test'))); // trueconsole.log(is('Date', new Date())); // true

正如你所看见的,替代方法可以处理更加常见例子,而且更加灵活。

3.类中不正确使用this

这可能是大家从Java转向学习JavaScript普遍头疼的问题。在Java中,this指向当时的对象,但在JavaScript事实并非如此。事实上,this有5种不同含义

代码语言:javascript
复制
// 1console.log(this); //指向全局对象也就是window// 包含了prompt alert confirm方法...// 2function test() {  console.log(this);  this.method = function inner() {console.log(this)};}; // 这里this也是指向全局对象test();//3var obj = new test(); // 因为用的是构造器,this指向test对象//4obj.method(); //方法迫使this指向对象// 5:使用call或apply迫使this指向明确的值function foo(a, b, c) {  this.a = a;  this.b = b;  this.c = c;}var bar = {};foo.apply(bar, [1, 2, 3]); //第一个参数为thisconsole.log(bar) // 会输出 a: 1, b: 2, c: 3foo.call(bar, 4, 5, 6); //同样的效果console.log(bar) //也会输出a: 4, b: 5, c: 6

这5个例子容易理解,然而第二个例子被认为是设计缺陷,因为会导致下面问题:

代码语言:javascript
复制
function test() {  this.arr = [1,2,4];  this.message = "I am here";  this.fun = function() {      this.arr.forEach(function(item) {        console.log(this.message); //会输出3次undefined,因为this指向全局对象    });  }}var t = new test();t.fun();//上面例子中,this不会指向test对象,而指向全局对象//为了避免这种情况,可以使用变量存储器this//虽然this仍指向全局对象,但是可以使用替代变量function test2() {  var self = this;  self.arr = [1,2,4];  self.message = "I am here";    self.fun = function() {      this.arr.forEach(function(item) {        console.log(self.message); //会输出I am here 3次    });  }}var t2 = new test2();t2.fun();

4.不使用匿名包装

JavaScript只有函数作用域,而且所有对象都分享在一个全局命名空间下,在大的项目中,这会带来很大的问题。

代码语言:javascript
复制
var foo = 12;function changeFoo() {  foo = 34; //改变的是全局作用域而不是局部作用域}changeFoo();console.log(foo);//输出34// 在下个例子显然会出现问题// Out here is the global scopefor(var i = 0; i < 10; i++) {    innerLoop();}function innerLoop() {    // 这是个不同的作用域    for(i = 0; i < 10; i++) { // 缺少var语句,i指向全局作用域           console.log("this is will show 10 times and not 100.");//只会输出10次    }}

为了避免这样问题,可以使用所谓的匿名包装器。实际上就是立即执行函数。

不止他们能避免命名冲突,而且也能帮助你更好的组织你的代码。

代码语言:javascript
复制
(  // 将函数写在圆括号中  function(){}  // 返回函数对象)() // 立即调用// 也可以使用下面同样函数效果!function(){}()+function(){}()(function(){}());// 重要提醒// 如果像下面这样做,会重写全局对象 undefinedconsole.log(typeof undefined === "undefined") // truevar undefined = 123;console.log(typeof undefined === "undefined") // this is false! undefined is overwritten and replaced by the number 123// 可以通过匿名包装(function(undefined){console.log(undefined);})();

5.通过对象的键不正确迭代

有几种方法迭代对象的属性。可以使用Object.keys、Object.entriees或者for循环

代码语言:javascript
复制
// 给全局对象增加一个属性,所有对象都会继承这个对象,Object.prototype.WTF = "this should not be in your object";function a() {  this.unwanted = 10;  this.crap = "dhjbjbfdjbf";}function child() {  this.a = 1;  this.b = 2;}//child会继承自achild.prototype = new a();var obj = new child();for (var property in obj) { //此方法不仅比Object.keys慢,而且还包含父属性    console.log(property + ": " + obj[property]);}for (var property in obj) { //这会返回适合的键,但是仍比Object.keys慢     if(obj.hasOwnProperty(property))        console.log(property + ": " + obj[property]);}Object.keys(obj).map((e) => console.log(`key=${e}  value=${obj[e]}`)); // 最佳的方式Object.entries(obj).forEach(([key, value]) => console.log(`key=${key} value=${value}`)); //这也是不错的方法

6.省略分号

如果忘写分号,JavaScript会自动添加。但是这样会弄乱你的代码并造成错误,这里有两个著名的例子:

代码语言:javascript
复制
/**  这里编译器会在return后加分号,造成函数返回undefined**/function test(){  var name = "Hello";  return // 这里会加分号  {    name: name  }}/**  这个例子更奇怪,由于大括号,所以不会加分号,最终会显示类型错误,因为编译器会认为console.log()是函数,而 (someList || []) 是参数**/function test2(){  var someList = undefined  console.log("Hi!") // does not add it here!  (someList || []).map((item) => item) }

你应该使用linter确保分号不会忘记。除此之外,应该经常放置大括号在相应语句的同一行,避免出现意想不到的错误。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-08-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 京程一灯 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.使用==而不是===
  • 2.使用typeof
  • 3.类中不正确使用this
  • 4.不使用匿名包装
  • 5.通过对象的键不正确迭代
  • 6.省略分号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档