diff --git src/wp-includes/taxonomy.php src/wp-includes/taxonomy.php
index 0fe83d6..e48d77e 100644
--- src/wp-includes/taxonomy.php
+++ src/wp-includes/taxonomy.php
@@ -1077,15 +1077,17 @@ function get_term_to_edit( $id, $taxonomy ) {
  * @since 4.4.0 Introduced the ability to pass 'term_id' as an alias of 'id' for the `orderby` parameter.
  *              Introduced the 'meta_query' and 'update_term_meta_cache' parameters. Converted to return
  *              a list of WP_Term objects.
- * @since 4.5.0 Introduced 'meta_key' and 'meta_value' parameters. Introduced the ability to order results by metadata.
+ * @since 4.5.0 Changed the function signature so that the `$args` array can be provided as the first parameter.
+ *              Introduced 'meta_key' and 'meta_value' parameters. Introduced the ability to order results by metadata.
  *
  * @global wpdb  $wpdb WordPress database abstraction object.
  * @global array $wp_filter
  *
- * @param string|array $taxonomies Taxonomy name or list of Taxonomy names.
  * @param array|string $args {
  *     Optional. Array or string of arguments to get terms.
  *
+ *     @type string|array $taxonomy               Taxonomy name, or array of taxonomies, to which results should
+ *                                                be limited.
  *     @type string       $orderby                Field(s) to order terms by. Accepts term fields ('name', 'slug',
  *                                                'term_group', 'term_id', 'id', 'description'), 'count' for term
  *                                                taxonomy count, 'include' to match the 'order' of the $include param,
@@ -1144,24 +1146,17 @@ function get_term_to_edit( $id, $taxonomy ) {
  *     @type string       $meta_value             Limit terms to those matching a specific metadata value. Usually used
  *                                                in conjunction with `$meta_key`.
  * }
+ * @param array $legacy_args Argument array, when using the legacy function parameter format. If present, this
+ *                           parameter will be interpreted as `$args`, and the first function parameter will
+ *                           be parsed as a taxonomy or array of taxonomies.
  * @return array|int|WP_Error List of WP_Term instances and their children. Will return WP_Error, if any of $taxonomies
  *                            do not exist.
  */
-function get_terms( $taxonomies, $args = '' ) {
+function get_terms( $args = array(), $legacy_args = '' ) {
 	global $wpdb;
-	$empty_array = array();
-
-	if ( ! is_array( $taxonomies ) ) {
-		$taxonomies = array( $taxonomies );
-	}
-
-	foreach ( $taxonomies as $taxonomy ) {
-		if ( ! taxonomy_exists($taxonomy) ) {
-			return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy' ) );
-		}
-	}
 
 	$defaults = array(
+		'taxonomy'               => null,
 		'orderby'                => 'name',
 		'order'                  => 'ASC',
 		'hide_empty'             => true,
@@ -1187,6 +1182,34 @@ function get_terms( $taxonomies, $args = '' ) {
 		'meta_query'             => ''
 	);
 
+	/*
+	 * Legacy argument format ($taxonomy, $args) takes precedence.
+	 *
+	 * We detect legacy argument format by checking if
+	 * (a) a second non-empty parameter is passed, or
+	 * (b) the first parameter shares no keys with the default array (ie, it's a list of taxonomies)
+	 */
+	$do_legacy_args = $legacy_args || empty( array_intersect_key( $defaults, (array) $args ) );;
+
+	$taxonomies = null;
+	if ( $do_legacy_args ) {
+		$taxonomies = (array) $args;
+		$args = $legacy_args;
+	} elseif ( isset( $args['taxonomy'] ) && null !== $args['taxonomy'] ) {
+		$taxonomies = (array) $args['taxonomy'];
+		unset( $args['taxonomy'] );
+	}
+
+	$empty_array = array();
+
+	if ( $taxonomies ) {
+		foreach ( $taxonomies as $taxonomy ) {
+			if ( ! taxonomy_exists($taxonomy) ) {
+				return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy' ) );
+			}
+		}
+	}
+
 	/**
 	 * Filter the terms query default arguments.
 	 *
@@ -1204,9 +1227,11 @@ function get_terms( $taxonomies, $args = '' ) {
 
 	// Save queries by not crawling the tree in the case of multiple taxes or a flat tax.
 	$has_hierarchical_tax = false;
-	foreach ( $taxonomies as $_tax ) {
-		if ( is_taxonomy_hierarchical( $_tax ) ) {
-			$has_hierarchical_tax = true;
+	if ( $taxonomies ) {
+		foreach ( $taxonomies as $_tax ) {
+			if ( is_taxonomy_hierarchical( $_tax ) ) {
+				$has_hierarchical_tax = true;
+			}
 		}
 	}
 
@@ -1309,7 +1334,9 @@ function get_terms( $taxonomies, $args = '' ) {
 		$order = 'ASC';
 	}
 
-	$where = "tt.taxonomy IN ('" . implode("', '", $taxonomies) . "')";
+	if ( $taxonomies ) {
+		$where = "tt.taxonomy IN ('" . implode("', '", $taxonomies) . "')";
+	}
 
 	$exclude = $args['exclude'];
 	$exclude_tree = $args['exclude_tree'];
@@ -1554,7 +1581,11 @@ function get_terms( $taxonomies, $args = '' ) {
 	$order = isset( $clauses[ 'order' ] ) ? $clauses[ 'order' ] : '';
 	$limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : '';
 
-	$query = "SELECT $distinct $fields FROM $wpdb->terms AS t $join WHERE $where $orderby $order $limits";
+	if ( $where ) {
+		$where = ' WHERE ' . $where;
+	}
+
+	$query = "SELECT $distinct $fields FROM $wpdb->terms AS t $join $where $orderby $order $limits";
 
 	// $args can be anything. Only use the args defined in defaults to compute the key.
 	$key = md5( serialize( wp_array_slice_assoc( $args, array_keys( $defaults ) ) ) . serialize( $taxonomies ) . $query );
diff --git tests/phpunit/tests/term/getTerms.php tests/phpunit/tests/term/getTerms.php
index 9f7facc..870f6a2 100644
--- tests/phpunit/tests/term/getTerms.php
+++ tests/phpunit/tests/term/getTerms.php
@@ -12,6 +12,43 @@ class Tests_Term_getTerms extends WP_UnitTestCase {
 	}
 
 	/**
+	 * @ticket 35495
+	 */
+	public function test_should_accept_an_args_array_containing_taxonomy_for_first_parameter() {
+		register_taxonomy( 'wptests_tax', 'post' );
+		$term = self::factory()->term->create( array( 'taxonomy' => 'wptests_tax' ) );
+
+		$found = get_terms( array(
+			'taxonomy' => 'wptests_tax',
+			'hide_empty' => false,
+			'fields' => 'ids',
+			'update_term_meta_cache' => false,
+		) );
+
+		$this->assertEqualSets( array( $term ), $found );
+	}
+
+	/**
+	 * @ticket 35495
+	 */
+	public function test_excluding_taxonomy_arg_should_return_terms_from_all_taxonomies() {
+		register_taxonomy( 'wptests_tax1', 'post' );
+		register_taxonomy( 'wptests_tax2', 'post' );
+		$t1 = self::factory()->term->create( array( 'taxonomy' => 'wptests_tax1' ) );
+		$t2 = self::factory()->term->create( array( 'taxonomy' => 'wptests_tax2' ) );
+
+		$found = get_terms( array(
+			'hide_empty' => false,
+			'fields' => 'ids',
+			'update_term_meta_cache' => false,
+		) );
+
+		// There may be other terms lying around, so don't do an exact match.
+		$this->assertContains( $t1, $found );
+		$this->assertContains( $t2, $found );
+	}
+
+	/**
 	 * @ticket 23326
 	 */
 	public function test_get_terms_cache() {
