如何在回调中访问正确的 this

2024-11-02 21:00:00
admin
原创
35
摘要:问题描述:我有一个注册事件处理程序的构造函数:function MyConstructor(data, transport) { this.data = data; transport.on('data', function () { ale...

问题描述:

我有一个注册事件处理程序的构造函数:

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', function () {
        alert(this.data);
    });
}

// Mock transport object
var transport = {
    on: function(event, callback) {
        setTimeout(callback, 1000);
    }
};

// called as
var obj = new MyConstructor('foo', transport);

运行代码片段Hide results展开片段

但是,我无法data在回调中访问已创建对象的属性。它似乎this不引用已创建的对象,而是引用另一个对象。

我还尝试使用对象方法而不是匿名函数:

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', this.alert);
}

MyConstructor.prototype.alert = function() {
    alert(this.name);
};

但它也存在同样的问题。

我如何才能访问正确的对象?


解决方案 1:

您应该了解的内容this

this(又名“上下文”)是每个函数内的一个特殊关键字,其值仅取决于函数的调用方式,而不是定义方式/时间/地点。它不受词法作用域的影响,就像其他变量一样(箭头函数除外,见下文)。以下是一些示例:

function foo() {
    console.log(this);
}

// normal function call
foo(); // `this` will refer to `window`

// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`

// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`

要了解更多信息this,请查看MDN 文档。


如何引用正确的this

使用箭头函数

ECMAScript 6 引入了箭头函数,可以将其视为 lambda 函数。它们没有自己的this绑定。相反,this它会像普通变量一样在作用域中查找。这意味着您不必调用.bind。这不是它们唯一的特殊行为,请参阅 MDN 文档了解更多信息。

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', () => alert(this.data));
}

不要使用this

实际上,您并不想访问this特定的对象,而是访问它所引用的对象。因此,一个简单的解决方案就是创建一个也引用该对象的新变量。变量可以有任何名称,但常见的名称是selfthat

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function() {
        alert(self.data);
    });
}

由于self是普通变量,因此它遵循词法作用域规则,并且可以在回调内部访问。这还有一个优点,即您可以访问this回调本身的值。

明确设置this回调 - 第 1 部分

可能看起来您无法控制的值,this因为它的值是自动设置的,但事实并非如此。

每个函数都有方法.bind [docs],它返回一个this绑定到值的新函数。该函数的行为与您调用的函数完全相同.bind,只是this由您设置。无论如何或何时调用该函数,this将始终引用传递的值。

function MyConstructor(data, transport) {
    this.data = data;
    var boundFunction = (function() { // parenthesis are not necessary
        alert(this.data);             // but might improve readability
    }).bind(this); // <- here we are calling `.bind()` 
    transport.on('data', boundFunction);
}

在这种情况下,我们将回调与的this值绑定。MyConstructor`this`

注意:当绑定 jQuery 上下文时,请改用jQuery.proxy [docs]。这样做的原因是,在解除事件回调绑定时,您无需存储对函数的引用。jQuery 会在内部处理该问题。

this回调函数设置- 第 2 部分

一些接受回调的函数/方法也接受回调this应该引用的值。这基本上与自己绑定相同,但函数/方法会为您完成绑定。Array#map [docs]就是这样一种方法。它的签名是:

array.map(callback[, thisArg])

第一个参数是回调,第二个参数是this应该引用的值。这是一个人为的例子:

var arr = [1, 2, 3];
var obj = {multiplier: 42};

var new_arr = arr.map(function(v) {
    return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument

注意:是否可以传递值this通常会在该函数/方法的文档中提及。例如,jQuery 的$.ajax方法[docs]描述了一个名为的选项context

该对象将成为所有 Ajax 相关回调的上下文。


常见问题:使用对象方法作为回调/事件处理程序

此问题的另一个常见表现是将对象方法用作回调/事件处理程序。函数是 JavaScript 中的一等公民,术语“方法”只是函数的口语术语,该函数是对象属性的值。但该函数与其“包含”对象没有特定的链接。

请考虑以下示例:

function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = function() {
    console.log(this.data);
};

函数this.method被指定为点击事件处理程序,但如果document.body单击了,则记录的值将是undefined,因为在事件处理程序中,this引用的是document.body,而不是的实例Foo

正如开头所提到的,引用this取决于函数的调用方式而不是定义方式。

如果代码如下所示,函数没有对对象的隐式引用可能更明显:

function method() {
    console.log(this.data);
}


function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = method;

解决方案与上面提到的相同:如果可用,使用.bind显式绑定this到特定值

document.body.onclick = this.method.bind(this);

或者明确地将该函数作为对象的“方法”来调用,通过使用匿名函数作为回调/事件处理程序并将对象(this)分配给另一个变量:

var self = this;
document.body.onclick = function() {
    self.method();
};

或者使用箭头函数:

document.body.onclick = () => this.method();

解决方案 2:

以下是在子上下文中访问父上下文的几种方法 -

  1. 您可以使用该bind()功能。

  2. 将对 context/this 的引用存储在另一个变量中(参见下面的示例)。

  3. 使用 ES6箭头函数。

  4. 改变代码、功能设计和架构——为此您应该掌握JavaScript 中的设计模式。

  5. 使用bind()函数

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', ( function () {
        alert(this.data);
    }).bind(this) );
}
// Mock transport object
var transport = {
    on: function(event, callback) {
        setTimeout(callback, 1000);
    }
};
// called as
var obj = new MyConstructor('foo', transport);

如果你使用 Underscore.js - http://underscorejs.org/#bind

transport.on('data', _.bind(function () {
    alert(this.data);
}, this));
  1. 将对 context/this 的引用存储在另一个变量中

function MyConstructor(data, transport) {
  var self = this;
  this.data = data;
  transport.on('data', function() {
    alert(self.data);
  });
}

3.箭头函数

function MyConstructor(data, transport) {
  this.data = data;
  transport.on('data', () => {
    alert(this.data);
  });
}

解决方案 3:

这一切都在调用方法的“神奇”语法中:

object.property();

当你从对象中获取属性并一次性调用它时,对象将成为该方法的上下文。如果你调用相同的方法,但在不同的步骤中,上下文将是全局范围(窗口):

var f = object.property;
f();

当你获取方法的引用时,它不再附加到对象。它只是对普通函数的引用。当你获取引用以用作回调时,也会发生同样的情况:

this.saveNextLevelData(this.setAll);

这就是你将上下文绑定到函数的地方:

this.saveNextLevelData(this.setAll.bind(this));

如果您使用 jQuery,则应改用该$.proxy方法,因为bind并非所有浏览器都支持该方法:

this.saveNextLevelData($.proxy(this.setAll, this));

解决方案 4:

应该 了解“this”关键字。

按照我的观点,你可以通过三种方式实现“this”
(Self|Arrow function|Bind Method)

与其他语言相比,函数this关键字在 JavaScript 中的行为略有不同。

严格模式和非严格模式也有一些区别。

大多数情况下,this 的值由函数的调用方式决定。

它不能在执行过程中通过赋值来设置,并且每次调用函数时它可能都不同。

ES5 引入了 bind() 方法来设置函数的值,this而不管它是如何调用的,

ES2015 引入了不提供自身this绑定的箭头函数(它保留了封闭词法上下文的 this 值)。

方法 1: Self - 即使上下文发生变化,Self 也用于维护对原始 this 的引用。这是事件处理程序中经常使用的一种技术(尤其是在闭包中)。

参考这个

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function () {
        alert(self.data);
    });
}

方法 2:箭头函数 - 箭头函数表达式是正则函数表达式的语法紧凑的替代方法,尽管它没有与 this、arguments、super 或 new.target 关键字的绑定。

箭头函数表达式不适合用作方法,并且不能用作构造函数。

参考箭头函数表达式

  function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data',()=> {
        alert(this.data);
    });
}

方法 3:绑定 - bind() 方法创建一个新函数,当调用该函数时,其this关键字设置为提供的值,并且在调用新函数时,在提供的任何参数之前设置给定的参数序列。

参考: Function.prototype.bind()

  function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data',(function() {
        alert(this.data);
    }).bind(this);

解决方案 5:

“背景”的问题

术语“上下文”有时用于指代this所引用的对象。它的使用并不恰当,因为它在语义上和技术上都不符合ECMAScript 的this

“上下文”是指围绕某事物的环境,这些环境赋予了事物意义,或者一些前后信息赋予了额外的意义。ECMAScript 中使用的术语“上下文”是指执行上下文,即某些执行代码范围内的所有参数、作用域和this

ECMA-262 第 10.4.2 节中显示了这一点:

将 ThisBinding 设置为与调用执行上下文的 ThisBinding 相同的值

这清楚地表明是执行上下文的一部分。

执行上下文提供了周围信息,为正在执行的代码添加了意义。它包含的信息远不止thisBinding

this的值不是“上下文”。它只是执行上下文的一部分。它本质上是一个局部变量,可以通过对任何对象的调用来设置,在严格模式下,可以将其设置为任何值。

解决方案 6:

首先,需要对关键字的上下文scope及其行为有一个清晰的认识。thisscope

this& scope


JavaScript 中有两种类型的作用域。它们是:

  1. 全局范围

  2. 函数作用域

简而言之,全局作用域指的是窗口对象。在全局作用域中声明的变量可以从任何地方访问。

另一方面,函数作用域位于函数内部。函数内部声明的变量通常无法从外部访问。

全局范围内的关键字this引用窗口对象。this函数内部也引用窗口对象。因此this将始终引用窗口,直到我们找到一种操作方法this来指示我们自己选择的上下文。

--------------------------------------------------------------------------------
-                                                                              -
-   Global Scope                                                               -
-   (globally "this" refers to window object)                                  -
-                                                                              -
-   function outer_function(callback){                                         -
-                                                                              -
-       // Outer function scope                                                -
-       // Inside the outer function, the "this" keyword                       -
-       //  refers to window object                                            -
-       callback() // "this" inside callback also refers to the  window object -
-   }                                                                          -
-                                                                              -
-   function callback_function(){                                              -
-                                                                              -
-       // Function to be passed as callback                                   -
-                                                                              -
-       // Here "THIS" refers to the window object also                        -
-   }                                                                          -
-                                                                              -
-   outer_function(callback_function)                                          -
-   // Invoke with callback                                                    -
-                                                                              -
--------------------------------------------------------------------------------

操作this回调函数内部的不同方法:

这里我有一个名为 Person 的构造函数。它有一个名为的属性name和四个方法,分别称为、、sayNameVersion1和。这四个方法都有一个特定的任务。接受回调并调用它。回调有一个特定的任务,即记录 Person 构造函数实例的 name 属性。sayNameVersion2sayNameVersion3sayNameVersion4

function Person(name){

    this.name = name

    this.sayNameVersion1 = function(callback){
        callback.bind(this)()
    }
    this.sayNameVersion2 = function(callback){
        callback()
    }

    this.sayNameVersion3 = function(callback){
        callback.call(this)
    }

    this.sayNameVersion4 = function(callback){
        callback.apply(this)
    }

}

function niceCallback(){

    // Function to be used as callback

    var parentObject = this

    console.log(parentObject)
}

现在让我们从 person 构造函数创建一个实例,并调用不同版本sayNameVersionX(X 指的是 1,2,3,4) 方法,niceCallback看看我们可以通过多少种方式操纵this内部回调来引用该person实例。

var p1 = new Person('zami') // Create an instance of Person constructor

绑定(bind):

bind 所做的是创建一个新函数,并将this关键字设置为提供的值。

sayNameVersion1sayNameVersion2使用bind来操作this回调函数。

this.sayNameVersion1 = function(callback){
    callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
    callback()
}

第一个方法this在方法本身内部绑定回调函数。而对于第二个方法,回调函数通过绑定到它的对象传递。

p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method

p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback

称呼:

first argument方法的用作call附加到它的this调用函数的内部call

sayNameVersion3用来call操纵this引用我们创建的 person 对象,而不是 window 对象。

this.sayNameVersion3 = function(callback){
    callback.call(this)
}

它的调用方式如下:

p1.sayNameVersion3(niceCallback)

申请:

与 类似call, 的第一个参数apply指的是将由关键字指示的对象this

sayNameVersion4用来apply操纵this指代人对象

this.sayNameVersion4 = function(callback){
    callback.apply(this)
}

它的调用方式如下。只需传递回调即可,

p1.sayNameVersion4(niceCallback)

解决方案 7:

我们不能将 this 绑定到,因为它总是与全局对象 (Window)setTimeout()一起执行。如果您想在回调函数中访问上下文,那么通过使用回调函数,我们可以实现它:this`bind()`

setTimeout(function(){
    this.methodName();
}.bind(this), 2000);

解决方案 8:

问题围绕this关键字在 JavaScript 中的行为方式。this其行为方式不同,如下所示,

  1. 的值this通常由函数执行上下文决定。

  2. 在全局作用域中,this指的是全局对象(window即对象)。

  3. 如果任何函数启用了严格模式,那么的值this将与严格模式下一样,全局对象代替对象undefined引用。undefined`window`

  4. 点之前的对象就是关键字this将要绑定的对象。

  5. call()我们可以使用、bind()和明确设置此值apply()

  6. new使用关键字(构造函数)时,this 会绑定到正在创建的新对象。

  7. 箭头函数不绑定this - 而是this按词汇绑定(即基于原始上下文)

正如大多数答案所建议的那样,我们可以使用箭头函数或bind()方法或 Self变量。我将引用Google JavaScript 样式指南中关于 lambda(箭头函数)的一点

优先使用箭头函数,而不是 f.bind(this),尤其是 goog.bind(f, this)。避免写 const self = this。箭头函数对于回调特别有用,回调有时会传递意外的额外参数。

Google 明确建议使用 lambda,而不是 bind 或const self = this

因此最好的解决方案是使用如下的 lambda,

function MyConstructor(data, transport) {
  this.data = data;
  transport.on('data', () => {
    alert(this.data);
  });
}

参考:

  1. https://medium.com/tech-tajawal/javascript-this-4-rules-7354abdb274c

  2. 箭头函数与绑定

解决方案 9:

当前,如果在代码中使用类,则还有另一种可行的方法。

在类字段的支持下,可以按以下方式实现:

class someView {
    onSomeInputKeyUp = (event) => {
        console.log(this); // This refers to the correct value
    // ....
    someInitMethod() {
        //...
        someInput.addEventListener('input', this.onSomeInputKeyUp)

当然,在底层,它都是绑定上下文的旧的好箭头函数,但在这种形式下,它看起来比显式绑定更清晰。

因为它是第 3 阶段提案,所以目前(2018 年 8 月)您将需要Babel和适当的Babel 插件来处理它。

解决方案 10:

另一种方法是自 DOM2 以来在事件监听器中绑定的标准方法,它允许您随时删除监听器(还有其他好处),它是来自接口的方法:this`handleEvent(evt)`EventListener

var obj = {
  handleEvent(e) {
    // always true
    console.log(this === obj);
  }
};

document.body.addEventListener('click', obj);

有关使用的详细信息handleEvent可以在这里找到:DOM handleEvent:自 2000 年以来的跨平台标准

解决方案 11:

Ngx我在使用折线图函数时遇到了一个问题xAxisTickFormatting,它是从 HTML 调用的,如下所示:[xAxisTickFormatting]="xFormat"

我无法从声明的函数访问组件的变量。此解决方案帮助我解决了问题并找到了正确的 this。

不要使用这样的函数:

xFormat (value): string {
  return value.toString() + this.oneComponentVariable; //gives wrong result
}

使用这个:

 xFormat = (value) => {
   // console.log(this);
   // now you have access to your component variables
   return value + this.oneComponentVariable
 }

解决方案 12:

this在 JavaScript 中:

JavaScript 中的 的值this100% 取决于函数的调用方式,而不是定义方式。我们可以相对轻松地this通过“点左侧规则”找到 的值:

  1. 当使用 function 关键字创建函数时,其值this是被调用函数的点左边的对象

  2. 如果点后面没有对象,那么this函数内部的值通常是全局对象(global在 Node.js 和window浏览器中)。我不建议this在这里使用关键字,因为它不如使用window!之类的东西那么明确。

  3. 存在某些结构,例如箭头函数和使用Function.prototype.bind()a 函数创建的函数,它们可以固定 的值this。这些是规则的例外,但它们对于固定 的值确实很有帮助this

Node.js 中的示例

module.exports.data = 'module data';
// This outside a function in node refers to module.exports object
console.log(this);

const obj1 = {
    data: "obj1 data",
    met1: function () {
        console.log(this.data);
    },
    met2: () => {
        console.log(this.data);
    },
};

const obj2 = {
    data: "obj2 data",
    test1: function () {
        console.log(this.data);
    },
    test2: function () {
        console.log(this.data);
    }.bind(obj1),
    test3: obj1.met1,
    test4: obj1.met2,
};

obj2.test1();
obj2.test2();
obj2.test3();
obj2.test4();
obj1.met1.call(obj2);

输出:

在此处输入图片描述

让我逐一向您介绍输出(从第二条日志开始忽略第一条日志):

  1. thisobj2因为点左边的规则,我们可以看到test1是如何调用的obj2.test1();obj2在点的左边,因此是this值的左边。

  2. 尽管obj2位于点的左侧,但仍通过方法test2绑定到。其值为。obj1`bind()thisobj1`

  3. obj2位于所调用函数的点的左侧:obj2.test3()。因此obj2的值将是this

  4. 在这种情况下:obj2.test4() obj2在点的左边。但是,箭头函数没有自己的this绑定。因此它将绑定到this外部范围的值,即module.exports在开始时记录的对象。

  5. this我们还可以使用函数指定值call。在这里,我们可以将所需的值作为参数传入this,在本例中就是obj2

解决方案 13:

其他人已经谈到了如何使用 .bind() 方法,但具体来说,如果有人在让它们一起工作时遇到困难,这里是如何将它与 .then() 一起使用:

someFunction()
.then(function(response) {
    //'this' wasn't accessible here before but now it is
}.bind(this))

正如评论中提到的,另一种方法是使用没有自己的“this”值的箭头函数

someFunction()
.then((response)=>{
    //'this' was always accessible here
})

解决方案 14:

您可以使用箭头函数来避免这个问题。

const functionToTest = (dataToSet , transport) => {
  this.dataToSet = dataToSet ;
  transport.on('dataToSet ', () => {
    console.log(this.dataToSet);
  });
}

解决方案 15:

2024 年答案

这里有很多信息已经过时了。这个答案主要讨论如何在 2024 年及以后解决

  1. 调用函数时使用实例

  • 永远不要将函数“从其实例中”取出。如果您稍后需要调用该函数,只需保留整个实例,例如这样:

class A {
  constructor(id) {
    this.id = id;
  }

  someFunction(){
    console.log(this);
  }
}

const a1 = new A(5);
const a2 = new A(20);
const arr = [a1, a2];

// some business logic

arr.forEach(a => a.someFunction());

运行代码片段Hide results展开片段

  1. 不要过度使用 this

如果没有必要,请不要使用this和类。当您需要存储库、控制器、服务等文件时,它默认会创建单例,这是您想要的(它基本上类似于 Java 中的 @Autowired,但是是原生的)。单例不需要类和“this”,无论您需要定义什么,请在文件根目录下定义。然后只需导出您想要的函数/变量。如果您不使用this,就不会有问题this

例如somethingService.js看起来类似于下面的代码:

const someDefaultValue = 10;

export function doSomething() {
   console.log(someDefaultValue);
}

那么您不必考虑直接使用doSomething()assomethingService.doSomething()doSomething()。 (它将发挥相同的作用)

  1. 使用 apply/call/bind

我个人并不喜欢广泛使用apply(或call或,bind它们基本上相同,只是叫法略有不同),根据我的经验,这会给代码带来更多混乱。但在某些情况下你可能需要它,所以我会在这里列出它。你基本上可以this在函数内部“注入”任何你喜欢的对象。

    class Simple { 
      constructor(id) {
        this.id = id;
      }

      showThis(text) {
        console.log(this, ` ** ${text} **`)
      }
    }
    
    
const simple = new Simple(25);
const showThisFn = simple.showThis;
showThisFn("using it without apply");
showThisFn.apply(simple, ["using it with apply"])
showThisFn.call(simple, "using it with call - basically same as apply, only syntactic sugar difference today")
boundShowThisFn = showThisFn.bind(simple);
boundShowThisFn("now it is bound with the function, so you dont have to specify it when calling it");

运行代码片段Hide results展开片段

  1. 正确使用箭头函数 =>

如果函数内部有函数,并且使用this,箭头函数将以this您期望的方式传递上下文。使用function关键字将改变 的上下文this

(基本上,只要可能并且安全,就使用箭头函数)

class A {
  constructor(baseValue) {
    this.baseValue = baseValue;
  }

  doMathArrowFunction(arr){
    arr.forEach(item => {
      console.log(`Arrow function: item is ${item} and this?.baseValue is ${this?.baseValue}`);
      console.log(item + this?.baseValue);
    });
  }
      

  doMathOldWay(arr) {
    arr.forEach(function(item) {
      console.log(`Old fashion function: item is ${item} and this?.baseValue is ${this?.baseValue}`);
      console.log(item + this?.baseValue);
    });
  }
}
 

const x = [1,2];
const a = new A(10);
a.doMathArrowFunction(x);
a.doMathOldWay(x);

运行代码片段Hide results展开片段

过去(在 Arrow 函数出现之前),这个问题通常用self/that关键字来解决。如果你遇到这个问题并想了解更多信息 - 请查看此主题中已接受的答案。

解决方案 16:

这就是我解决问题的方法

class myClass
{
    constructor(parent)
    {
        this.callback = (function() { 
            this.callbackFunctionOfParent();             
        }).bind(parent);
    }

    callCallback() {
         this.callback();
    }
}

class Class2
{
       constructor()
       {
            this.Name = "CLASS 2";

            this.test = new myClass(this);

            this.test.callCallback();
       } 

       callbackFunctionOfParent()
       {
           console.log("parent is: " + this.Name);
       }
}

var c2 = new Class2;

运行代码片段Hide results展开片段

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用