diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
index a6c6bed..441bd86 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
@@ -150,11 +150,12 @@ public function setValue($values, $notify = TRUE) {
       }
     }
     else {
-      // Make sure that the 'entity' property gets set as 'target_id'.
-      if (isset($values['target_id']) && !isset($values['entity'])) {
-        $values['entity'] = $values['target_id'];
-      }
-      parent::setValue($values, $notify);
+      parent::setValue($values, FALSE);
+      // Invoke our own onChange method to account for $values which contain
+      // only one property (target_id or entity) and we need to synchronize the
+      // other one.
+      $property_name = is_array($values) ? key($values) : NULL;
+      $this->onChange($property_name, $notify);
     }
   }
 
@@ -174,8 +175,12 @@ public function getValue($include_computed = FALSE) {
 
   /**
    * {@inheritdoc}
+   *
+   * @param bool $notify_parent
+   *   (optional) Whether the parent should be notified of changes. Defaults to
+   *   TRUE.
    */
-  public function onChange($property_name) {
+  public function onChange($property_name, $notify_parent = TRUE) {
     // Make sure that the target ID and the target property stay in sync.
     if ($property_name == 'target_id') {
       $this->properties['entity']->setValue($this->target_id, FALSE);
@@ -183,7 +188,9 @@ public function onChange($property_name) {
     elseif ($property_name == 'entity') {
       $this->set('target_id', $this->properties['entity']->getTargetIdentifier(), FALSE);
     }
-    parent::onChange($property_name);
+    if ($notify_parent) {
+      parent::onChange($property_name);
+    }
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php
index 961eb67..958293e 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php
@@ -79,11 +79,12 @@ public function setValue($values, $notify = TRUE) {
       }
     }
     else {
-      // Make sure that the 'language' property gets set as 'value'.
-      if (isset($values['value']) && !isset($values['language'])) {
-        $values['language'] = $values['value'];
-      }
-      parent::setValue($values, $notify);
+      parent::setValue($values, FALSE);
+      // Invoke our own onChange method to account for $values which contain
+      // only one property (value or language) and we need to synchronize the
+      // other one.
+      $property_name = is_array($values) ? key($values) : NULL;
+      $this->onChange($property_name, $notify);
     }
   }
 
@@ -99,8 +100,12 @@ public function applyDefaultValue($notify = TRUE) {
 
   /**
    * {@inheritdoc}
+   *
+   * @param bool $notify_parent
+   *   (optional) Whether the parent should be notified of changes. Defaults to
+   *   TRUE.
    */
-  public function onChange($property_name) {
+  public function onChange($property_name, $notify_parent = TRUE) {
     // Make sure that the value and the language property stay in sync.
     if ($property_name == 'value') {
       $this->properties['language']->setValue($this->value, FALSE);
@@ -108,6 +113,8 @@ public function onChange($property_name) {
     elseif ($property_name == 'language') {
       $this->set('value', $this->properties['language']->getTargetIdentifier(), FALSE);
     }
-    parent::onChange($property_name);
+    if ($notify_parent) {
+      parent::onChange($property_name);
+    }
   }
 }
diff --git a/core/modules/entity_reference/src/Tests/EntityReferenceItemTest.php b/core/modules/entity_reference/src/Tests/EntityReferenceItemTest.php
index db91b59..b0034c8 100644
--- a/core/modules/entity_reference/src/Tests/EntityReferenceItemTest.php
+++ b/core/modules/entity_reference/src/Tests/EntityReferenceItemTest.php
@@ -105,10 +105,24 @@ public function testContentEntityReferenceItem() {
     ));
     $term2->save();
 
-    $entity->field_test_taxonomy_term->target_id = $term2->id();
+    // Test all the possible ways of assigning a value.
+    $entity->field_test_taxonomy_term->target_id = $term->id();
+    $this->assertEqual($entity->field_test_taxonomy_term->entity->id(), $term->id());
+    $this->assertEqual($entity->field_test_taxonomy_term->entity->getName(), $term->getName());
+
+    $entity->field_test_taxonomy_term = [['target_id' => $term2->id()]];
     $this->assertEqual($entity->field_test_taxonomy_term->entity->id(), $term2->id());
     $this->assertEqual($entity->field_test_taxonomy_term->entity->getName(), $term2->getName());
 
+    // Test value assignment via the computed 'entity' property.
+    $entity->field_test_taxonomy_term->entity = $term;
+    $this->assertEqual($entity->field_test_taxonomy_term->target_id, $term->id());
+    $this->assertEqual($entity->field_test_taxonomy_term->entity->getName(), $term->getName());
+
+    $entity->field_test_taxonomy_term = [['entity' => $term2]];
+    $this->assertEqual($entity->field_test_taxonomy_term->target_id, $term2->id());
+    $this->assertEqual($entity->field_test_taxonomy_term->entity->getName(), $term2->getName());
+
     // Delete terms so we have nothing to reference and try again
     $term->delete();
     $term2->delete();
