How to check if a string starts with another string in JavaScript?
How would I write the equivalent of C#'s String.StartsWith method in JavaScript?
Example:
var haystack = 'hello world';
var needle = 'he';
haystack.startsWith(needle) == true
Note: This is an old question, and as pointed out in the comments ECMAScript 2015 (ES6) introduced the .startsWith method. However, at the time of writing this update (2015) browser support is far from complete.
The modern way to check if a string starts with another string in JavaScript is using the String.prototype.startsWith() method introduced in ECMAScript 2015 (ES6). This method returns true if the string begins with the specified characters, and false otherwise. For older browsers that don’t support ES6, you can use polyfills or alternative approaches like indexOf() or substr() comparisons.
Contents
- Using the Modern startsWith() Method
- Browser Compatibility and Polyfills
- Alternative Methods for Older Browsers
- Practical Examples and Use Cases
- Performance Considerations
- Complete Solution with Fallback
Using the Modern startsWith() Method
The startsWith() method is the most elegant and readable solution for checking if a string begins with another string. It’s part of the ES6 specification and provides a clean, intuitive API.
Basic Syntax
string.startsWith(searchString[, position])
searchString: The characters to be searched for at the start of the stringposition: Optional. The position in this string at which to begin searching forsearchString; defaults to 0
Examples
const str = 'Hello World';
// Basic usage
console.log(str.startsWith('Hello')); // true
console.log(str.startsWith('World')); // false
// Using position parameter
console.log(str.startsWith('World', 6)); // true (searches from index 6)
console.log(str.startsWith('lo', 3)); // true (searches from index 3)
Case Sensitivity
The startsWith() method is case-sensitive:
const str = 'Hello World';
console.log(str.startsWith('hello')); // false
console.log(str.startsWith('Hello')); // true
Edge Cases
const str = 'Hello World';
// Empty string always returns true
console.log(str.startsWith('')); // true
// String shorter than search string
console.log(str.startsWith('Hello World!')); // false
Browser Compatibility and Polyfills
While startsWith() is supported in all modern browsers, older browsers like Internet Explorer 11 do not support it natively. Here are several approaches to ensure compatibility:
1. Feature Detection and Polyfill
if (!String.prototype.startsWith) {
String.prototype.startsWith = function(searchString, position) {
position = position || 0;
return this.substr(position, searchString.length) === searchString;
};
}
2. Mathias Bynens’ Robust Polyfill
For a more comprehensive solution that exactly matches the ES6 specification, you can use Mathias Bynens’ polyfill available on GitHub:
// From: https://github.com/mathiasbynens/String.prototype.startsWith
if (!String.prototype.startsWith) {
(function() {
'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
var defineProperty = (function() {
try {
var o = {};
var func = Object.defineProperty;
return func(o, o, o) && func;
} catch (e) {
/* IE 8 has a broken Object.defineProperty */
}
}());
var toString = {}.toString;
var startsWith = ''[startsWith];
if (
defineProperty &&
toString.call(startsWith) === '[object Function]'
) {
defineProperty(String.prototype, 'startsWith', {
value: startsWith,
configurable: true,
writable: true
});
} else {
String.prototype.startsWith = startsWith;
}
})();
}
3. Using Core-js Library
For a more robust solution that includes many ES6 features, use the core-js library:
import 'core-js/features/string/starts-with';
Or in the browser:
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.6.12/core.min.js"></script>
Alternative Methods for Older Browsers
Before ES6, developers used various approaches to achieve the same functionality:
1. Using indexOf()
function startsWith(haystack, needle) {
return haystack.indexOf(needle) === 0;
}
// Usage
var haystack = 'hello world';
var needle = 'he';
console.log(startsWith(haystack, needle)); // true
2. Using substr()
function startsWith(haystack, needle) {
return haystack.substr(0, needle.length) === needle;
}
// Usage
var haystack = 'hello world';
var needle = 'he';
console.log(startsWith(haystack, needle)); // true
3. Using substring()
function startsWith(haystack, needle) {
return haystack.substring(0, needle.length) === needle;
}
// Usage
var haystack = 'hello world';
var needle = 'he';
console.log(startsWith(haystack, needle)); // true
4. Using slice()
function startsWith(haystack, needle) {
return haystack.slice(0, needle.length) === needle;
}
// Usage
var haystack = 'hello world';
var needle = 'he';
console.log(startsWith(haystack, needle)); // true
Practical Examples and Use Cases
URL Validation
function isValidUrl(url) {
return url.startsWith('http://') || url.startsWith('https://');
}
console.log(isValidUrl('https://example.com')); // true
console.log(isValidUrl('ftp://example.com')); // false
File Extension Check
function isImageFile(filename) {
return filename.startsWith('.jpg') || filename.startsWith('.png') ||
filename.startsWith('.gif') || filename.startsWith('.bmp');
}
console.log(isImageFile('image.jpg')); // true
console.log(isImageFile('document.pdf')); // false
Route Path Validation
function isSecureRoute(path) {
return path.startsWith('/admin') || path.startsWith('/dashboard') ||
path.startsWith('/api/private');
}
console.log(isSecureRoute('/admin/users')); // true
console.log(isSecureRoute('/public/home')); // false
Prefix Matching with Position
function hasProtocol(url) {
return url.startsWith('http://', 0) || url.startsWith('https://', 0);
}
function hasProtocolAt(url, position) {
return url.startsWith('http://', position) || url.startsWith('https://', position);
}
console.log(hasProtocol('https://example.com')); // true
console.log(hasProtocol('ftp://example.com')); // false
console.log(hasProtocolAt('Check: https://example.com', 7)); // true
Performance Considerations
When choosing between different methods, consider performance implications:
Performance Comparison
According to MDN documentation, the native startsWith() method is generally the most efficient. Alternative implementations can be compared as follows:
// Performance test setup
function testPerformance() {
const str = 'Hello World, this is a test string for performance';
const prefix = 'Hello World';
const iterations = 100000;
// Test startsWith()
console.time('startsWith');
for (let i = 0; i < iterations; i++) {
str.startsWith(prefix);
}
console.timeEnd('startsWith');
// Test indexOf()
console.time('indexOf');
for (let i = 0; i < iterations; i++) {
str.indexOf(prefix) === 0;
}
console.timeEnd('indexOf');
// Test substr()
console.time('substr');
for (let i = 0; i < iterations; i++) {
str.substr(0, prefix.length) === prefix;
}
console.timeEnd('substr');
}
Performance Rankings
Generally, the performance ranking from fastest to slowest is:
startsWith()(native implementation)indexOf() === 0substr()comparisonsubstring()comparisonslice()comparison
Complete Solution with Fallback
For a production-ready solution that works across all browsers, here’s a comprehensive approach:
1. Modern Approach with Feature Detection
// Check if startsWith is available, if not use polyfill
if (!String.prototype.startsWith) {
// Simple polyfill
String.prototype.startsWith = function(searchString, position) {
position = position || 0;
return this.substr(position, searchString.length) === searchString;
};
}
// Usage
var haystack = 'hello world';
var needle = 'he';
console.log(haystack.startsWith(needle)); // true
2. Library-Based Approach
// Using lodash/underscore
_.startsWith(haystack, needle);
// Or using a custom utility function
function safeStartsWith(str, search, position) {
if (String.prototype.startsWith) {
return str.startsWith(search, position);
} else {
position = position || 0;
return str.substr(position, search.length) === search;
}
}
3. Build Tool Integration
If you’re using a build tool like Webpack, you can automatically include polyfills:
// webpack.config.js
module.exports = {
// ... other config
entry: ['core-js/fn/string/starts-with', './app.js']
};
4. Progressive Enhancement Approach
// Define startsWith if not available
if (typeof String.prototype.startsWith !== 'function') {
String.prototype.startsWith = function(searchString, position) {
position = position || 0;
return this.indexOf(searchString, position) === position;
};
}
// Now you can use it everywhere
var url = 'https://example.com/path';
if (url.startsWith('https://')) {
// Handle secure connection
}
Sources
- String.prototype.startsWith() - JavaScript | MDN
- How to check if a string “StartsWith” another string? - Stack Overflow
- JavaScript - How to Check if a String “StartsWith” Another String in JavaScript? - GeeksforGeeks
- String startsWith() Method in JavaScript - Medium
- How to check if a string starts with another in JavaScript - Flavio Copes
- GitHub - mathiasbynens/String.prototype.startsWith
- Add startsWith in IE 11 - Stack Overflow
- Polyfills and Browser Compatibility - DEV Community
Conclusion
Checking if a string starts with another string in JavaScript is straightforward with the modern startsWith() method introduced in ES6. For the most readable and maintainable code, always prefer the native startsWith() method when targeting modern browsers. For maximum compatibility across all browsers, including older ones like Internet Explorer 11, implement a proper polyfill or use feature detection to provide fallback functionality. The alternative approaches using indexOf(), substr(), substring(), or slice() can be used when ES6 support is not available, though they may be slightly less performant than the native implementation. Always test your string prefixing logic thoroughly across your target browser environment to ensure consistent behavior.