在对象得第二个方法调用第一个对象得方法时,第一个方法没有定义?
发布于 10 年前 作者 youqingkui 6348 次浏览 最后一次编辑是 8 年前

在Test里面有两个方法,getInfo 与pushSeller,当我在pushSeller中调用getInfo时是为定义错误。请问是作用域得问题吗?谢谢!

function Test() {

  this.style = new Xinge.Style(4, 1, 1, 1, 0);

  this.getInfo = function (os, flag) {
    this.accessId = Number(process.env['XINGE_' + flag +'_' + os + '_ACCESS_ID']);
    this.secretKey = process.env['XINGE_' + flag + '_' + os + '_SECRET_KEY'];
    this.XingeApp = new Xinge.XingeApp(this.accessId, this.secretKey);
  }
  this.pushSeller = function (seller_id, title, content) {
    console.log(this.getInfo); //在这我可用访问到getInfo
    db.query(
      "SELECT * FROM seller_admin WHERE seller_id=?", [seller_id],
      function (err, seller_admin) {
        if (err) {
          return console.log(err);
        }
        
        if (seller_admin.length) {
          for (var i = 0; i < seller_admin.length; i++) {
            (function (i) {
              db.query(
                "SELECT os, pushtoken FROM user WHERE uid =?", [seller_admin[i].uid],
                function (err, user) {
                  if (err) {
                    return console.log(err);
                  }
                  if (user[0].pushtoken) {
                    if (user[0].os == 'android') {
                      console.log(user);
                      this.getInfo('ANDROID', 'SHOP'); //在这里我访问不到getInfo
                      this.android(user[0].pushtoken, title, content)
                    }
                  }
                }

              );
            })(i);
          }
        }
      }
    );
  }
}
45 回复

进回调了,肯定拿不到。 db.query() 明显进回调了。 //混合(MIX)方法到SESSION或者GLOBAL。是最佳解决方法。

@MiguelValentine 还是有点不理解,回调里面不能访问外部函数?要传参数?

@youqingkui 是啊,回调里面的方法拿不到外部函数。传参都没用呢。用公用变量或者全局变量解决吧。

this指向当前函数.你看看你用this时,this指向谁?

@MiguelValentine 不对。怎么可能拿不到? 闭包。

@ngot 难道我这个this没有指向到当前对象?

@youqingkui 指向了。但是当前对象是谁呢?

@ngot 我console.log(this),得道德是下面得东西。this变成了db.query?

{ domain: null,
  _events:
   { error: [Function],
     packet: [Function],
     end: [Function],
     timeout: [Function],
     'start-tls': [Function] },
  _maxListeners: 10,
  _callback: [Function],
  _callSite: null,
  _ended: true,
  _timeout: undefined,
  _idleNext: null,
  _idlePrev: null,
  _idleStart: null,
  _idleTimeout: undefined,
  _repeat: null,
  sql: 'SELECT os, pushtoken FROM user WHERE uid =15',
  values: [ 15 ],
  typeCast: true,
  nestTables: false,
  _resultSet: null,
  _results: [ [ [Object] ] ],
  _fields: [ [ [Object], [Object] ] ],
  _index: 1,
  _loadError: null,
  _connection:
   { domain: null,
     _events: { error: [Function] },
     _maxListeners: 10,
     config:
      { host: 'localhost',
        port: 3306,
        localAddress: undefined,
        socketPath: undefined,
        user: 'root',
        password: undefined,
        database: 'mykar_product',
        connectTimeout: 10000,
        insecureAuth: false,
        supportBigNumbers: false,
        bigNumberStrings: false,
        dateStrings: false,
        debug: undefined,
        trace: true,
        stringifyObjects: false,
        timezone: 'local',
        flags: '',
        queryFormat: undefined,
        pool: undefined,
        ssl: false,
        multipleStatements: false,
        typeCast: true,
        maxPacketSize: 0,
        charsetNumber: 33,
        clientFlags: 193487,
        protocol41: true },
     _socket:
      { _connecting: false,
        _handle: [Object],
        _readableState: [Object],
        readable: true,
        domain: null,
        _events: [Object],
        _maxListeners: 10,
        _writableState: [Object],
        writable: true,
        allowHalfOpen: false,
        onend: null,
        destroyed: false,
        bytesRead: 1344,
        _bytesDispatched: 253,
        _pendingData: null,
        _pendingEncoding: '',
        pipe: [Function],
        addListener: [Function],
        on: [Function],
        pause: [Function],
        resume: [Function],
        read: [Function],
        _consuming: true,
        _idleTimeout: -1,
        _idleNext: null,
        _idlePrev: null,
        _idleStart: 1407894192122 },
     _protocol:
      { domain: null,
        _events: [Object],
        _maxListeners: 10,
        readable: true,
        writable: true,
        _config: [Object],
        _connection: [Circular],
        _callback: null,
        _fatalError: null,
        _quitSequence: null,
        _handshakeSequence: [Object],
        _handshaked: true,
        _ended: false,
        _destroyed: false,
        _queue: [Object],
        _handshakeInitializationPacket: [Object],
        _parser: [Object] },
     _connectCalled: true,
     state: 'authenticated',
     threadId: 151 } }

@ngot 那请问,我如何在下面访问到Test得getInfo?谢谢!

@youqingkui 没有变啊。this永远指向当前对象啊。

@youqingkui 把getInfo做成闭包

@ngot 数据库是个坑爹异步。所以这里不存在闭包概念。用GLOBAL MIX this方法

gloabal.path = this;在上面声明,下面用global.path代替this.

@MiguelValentine 别用global,这是坑。作闭包,做保险。

@MiguelValentine 学习了,都是好方法!谢谢!

@ngot 我去掉对象Test里面得this.getInfo方法,在pushSeller里面定义一个。

function getInfo (os, flag) {
    this.accessId = Number(process.env['XINGE_' + flag +'_' + os + '_ACCESS_ID']);
    this.secretKey = process.env['XINGE_' + flag + '_' + os + '_SECRET_KEY'];
    this.XingeApp = new Xinge.XingeApp(this.accessId, this.secretKey);
  }

然后去掉下面得this.getInfo,改为getInfo(‘ANDROID’, ‘SHOP’);可以访问getInfo 了。

@youqingkui 这个方法,不错。安全。不过我的意思,不是传方法闭包。而是传外层对象的闭包,我觉得这样更优雅。

@ngot 外层对象得闭包?有点不理解,可否简单的给下代码?

@ngot 在Test里面这样定义getInfo? 然后在Test外面定义getInfo?

Test(){
this.getInfo = getInfo;

}
function getInfo(){
...
}

@youqingkui 没有很复杂,很简单的

function test1(){
   var  self = this;
    self.getInfo = function(){
    return "hello";
  }
   function test2(){
      self.getInfo();       
  }
}

@ngot 反正我觉得用SESSION最保险,也不会串。

@MiguelValentine 那样session就不纯粹了

@ngot 这个好像和那位朋友的方法有些类似,gloabal.path = this; 将对象的this带到闭包里面。

@youqingkui 不要污染全局。

@ngot session反正又不是COOKIES,是为会话服务的。在服务器端的保密数据而已。既然为会话服务,传值用起来绝对好。

@MiguelValentine 拆分session的时候,你怎么办?

@youqingkui 最好不要用global,项目大了调试起来是个大问题

@ngot session.cache具体怎么存看个人习惯。SESSION又不是JSON,是数组

@MiguelValentine 如果session做成分布式,还要进行I/O操作,蛋疼不蛋疼。海量流量的时候,会拖垮服务器的

@ngot 我这样字修改了一下,Test的两个方法再pushSeller付给,但是执行到getInfo2的时候,环境不是Test的,而是node的执行环境。

  this.pushSeller = function (seller_id, title, content) {
    var getInfo2 = this.getInfo;
    var android2 = this.android;
    
    db.query(
      "SELECT * FROM seller_admin WHERE seller_id=?", [seller_id],
      function (err, seller_admin) {
        if (err) {
          return console.log(err);
        }

        if (seller_admin.length) {
          for (var i = 0; i < seller_admin.length; i++) {
            (function (i) {
              db.query(
                "SELECT os, pushtoken FROM user WHERE uid =?", [seller_admin[i].uid],
                function (err, user) {
                  if (err) {
                    return console.log(err);
                  }
                  if (user[0].pushtoken) {
                    if (user[0].os == 'android') {
                      console.log(user);
                      getInfo2('ANDROID', 'SHOP');
                      android2(user[0].pushtoken, title, content)
                    }
                  }
                }

              );
            })(i);
          }
        }
      }
    );
  }

@youqingkui 你需要用call或者apply

@youqingkui 函数的上下文this,bind,call,apply搞懂特别重要

@ngot 你看他的模型,采用SESSION做的话,明显可以减少I/O。session做在REDIS内存里,比硬盘IO快多了把。

@MiguelValentine 真早这么做,会上最丑方案排行榜的

@ngot 你还真别说,我写的都是最丑最快的方案。

@MiguelValentine session维护的这些变量,你打算如何释放?

@MiguelValentine 在session过期时间内,海量请求,就会把内存撑爆

@MiguelValentine 正是因为放在redis内,才会有i/o开销。除非,你服务器,数据库是单台服务器。实际情况,哪有单台的。都是集群。跑起来网络i/o,还有硬件i/o,开销很大

@youqingkui

function Test() {
	var self = this;

	self.style = new Xinge.Style(4, 1, 1, 1, 0);

	self.getInfo = function(os, flag) {
		self.accessId = Number(process.env['XINGE_' + flag + '_' + os + '_ACCESS_ID']);
		self.secretKey = process.env['XINGE_' + flag + '_' + os + '_SECRET_KEY'];
		self.XingeApp = new Xinge.XingeApp(self.accessId, self.secretKey);
	};

	self.pushSeller = function(seller_id, title, content) {

		db.query(
			"SELECT * FROM seller_admin WHERE seller_id=?", [seller_id],
			function(err, seller_admin) {
				if (err) {
					return console.log(err);
				}

				if (seller_admin.length) {
					for (var i = 0; i < seller_admin.length; i++) {
						(function(i) {
							db.query(
								"SELECT os, pushtoken FROM user WHERE uid =?", [seller_admin[i].uid],
								function(err, user) {
									if (err) {
										return console.log(err);
									}
									if (user[0].pushtoken) {
										if (user[0].os == 'android') {
											console.log(user);
											self.getInfo.call(self, 'ANDROID', 'SHOP');
											self.android.call(self, user[0].pushtoken, title, content)
										}
									}
								}
							);
						})(i);
					}
				}
			}
		);
	}
}

@youqingkui 或者这样

this.pushSeller = function(seller_id, title, content) {
	var getInfo2 = this.getInfo.bind(this);
	var android2 = this.android.bind(this);

	db.query(
		"SELECT * FROM seller_admin WHERE seller_id=?", [seller_id],
		function(err, seller_admin) {
			if (err) {
				return console.log(err);
			}

			if (seller_admin.length) {
				for (var i = 0; i < seller_admin.length; i++) {
					(function(i) {
						db.query(
							"SELECT os, pushtoken FROM user WHERE uid =?", [seller_admin[i].uid],
							function(err, user) {
								if (err) {
									return console.log(err);
								}
								if (user[0].pushtoken) {
									if (user[0].os == 'android') {
										console.log(user);
										getInfo2('ANDROID', 'SHOP');
										android2(user[0].pushtoken, title, content)
									}
								}
							}
						);
					})(i);
				}
			}
		}
	);
}

@ngot 说的好像硬盘IO不要网络IO一样。还不如内存IO了

回到顶部