Как проверить, начинается ли строка с другой строки в JavaScript?
Как написать аналог метода C# String.StartsWith в JavaScript?
Пример:
var haystack = 'hello world';
var needle = 'he';
haystack.startsWith(needle) == true
Примечание: Это старый вопрос, и, как указано в комментариях, ECMAScript 2015 (ES6) представил метод .startsWith. Однако на момент написания этого обновления (2015) поддержка браузерами была далеко не полной.
Современный способ проверки, начинается ли строка с другой строки в JavaScript
Современный способ проверки, начинается ли одна строка с другой в JavaScript, — использование метода String.prototype.startsWith(), введенного в ECMAScript 2015 (ES6). Этот метод возвращает true, если строка начинается с указанных символов, и false в противном случае. Для старых браузеров, которые не поддерживают ES6, можно использовать полифилы или альтернативные подходы, такие как сравнения с использованием indexOf() или substr().
Содержание
- Использование современного метода startsWith()
- Совместимость с браузерами и полифилы
- Альтернативные методы для старых браузеров
- Практические примеры и случаи использования
- Вопросы производительности
- Полное решение с резервным вариантом
Использование современного метода startsWith()
Метод startsWith() является наиболее элегантным и читаемым решением для проверки, начинается ли строка с другой строки. Он является частью спецификации ES6 и предоставляет чистый, интуитивный API.
Базовый синтаксис
string.startsWith(searchString[, position])
searchString: Символы, которые нужно найти в начале строкиposition: Необязательный. Позиция в этой строке, с которой начинается поискsearchString; по умолчанию 0
Примеры
const str = 'Hello World';
// Базовое использование
console.log(str.startsWith('Hello')); // true
console.log(str.startsWith('World')); // false
// Использование параметра position
console.log(str.startsWith('World', 6)); // true (ищет с индекса 6)
console.log(str.startsWith('lo', 3)); // true (ищет с индекса 3)
Чувствительность к регистру
Метод startsWith() чувствителен к регистру:
const str = 'Hello World';
console.log(str.startsWith('hello')); // false
console.log(str.startsWith('Hello')); // true
Особые случаи
const str = 'Hello World';
// Пустая строка всегда возвращает true
console.log(str.startsWith('')); // true
// Строка короче искомой строки
console.log(str.startsWith('Hello World!')); // false
Совместимость с браузерами и полифилы
Хотя startsWith() поддерживается во всех современных браузерах, более старые браузеры, такие как Internet Explorer 11, не поддерживают его нативно. Вот несколько подходов для обеспечения совместимости:
1. Обнаружение возможностей и полифил
if (!String.prototype.startsWith) {
String.prototype.startsWith = function(searchString, position) {
position = position || 0;
return this.substr(position, searchString.length) === searchString;
};
}
2. Надежный полифил от Mathias Bynens
Для более комплексного решения, которое точно соответствует спецификации ES6, можно использовать полифил Mathias Bynens, доступный на GitHub:
// From: https://github.com/mathiasbynens/String.prototype.startsWith
if (!String.prototype.startsWith) {
(function() {
'use strict'; // необходимо для поддержки `apply`/`call` с `undefined`/`null`
var defineProperty = (function() {
try {
var o = {};
var func = Object.defineProperty;
return func(o, o, o) && func;
} catch (e) {
/* IE 8 имеет сломанный 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. Использование библиотеки Core-js
Для более надежного решения, включающего многие возможности ES6, используйте библиотеку core-js:
import 'core-js/features/string/starts-with';
Или в браузере:
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.6.12/core.min.js"></script>
Альтернативные методы для старых браузеров
До ES6 разработчики использовали различные подходы для достижения той же функциональности:
1. Использование indexOf()
function startsWith(haystack, needle) {
return haystack.indexOf(needle) === 0;
}
// Использование
var haystack = 'hello world';
var needle = 'he';
console.log(startsWith(haystack, needle)); // true
2. Использование substr()
function startsWith(haystack, needle) {
return haystack.substr(0, needle.length) === needle;
}
// Использование
var haystack = 'hello world';
var needle = 'he';
console.log(startsWith(haystack, needle)); // true
3. Использование substring()
function startsWith(haystack, needle) {
return haystack.substring(0, needle.length) === needle;
}
// Использование
var haystack = 'hello world';
var needle = 'he';
console.log(startsWith(haystack, needle)); // true
4. Использование slice()
function startsWith(haystack, needle) {
return haystack.slice(0, needle.length) === needle;
}
// Использование
var haystack = 'hello world';
var needle = 'he';
console.log(startsWith(haystack, needle)); // true
Практические примеры и случаи использования
Валидация URL
function isValidUrl(url) {
return url.startsWith('http://') || url.startsWith('https://');
}
console.log(isValidUrl('https://example.com')); // true
console.log(isValidUrl('ftp://example.com')); // false
Проверка расширения файла
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
Валидация пути маршрута
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
Сопоставление префикса с позицией
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
Вопросы производительности
При выборе между разными методами учитывайте производительность:
Сравнение производительности
Согласно документации MDN, нативный метод startsWith() обычно является наиболее эффективным. Альтернативные реализации можно сравнить следующим образом:
// Настройка теста производительности
function testPerformance() {
const str = 'Hello World, this is a test string for performance';
const prefix = 'Hello World';
const iterations = 100000;
// Тест startsWith()
console.time('startsWith');
for (let i = 0; i < iterations; i++) {
str.startsWith(prefix);
}
console.timeEnd('startsWith');
// Тест indexOf()
console.time('indexOf');
for (let i = 0; i < iterations; i++) {
str.indexOf(prefix) === 0;
}
console.timeEnd('indexOf');
// Тест substr()
console.time('substr');
for (let i = 0; i < iterations; i++) {
str.substr(0, prefix.length) === prefix;
}
console.timeEnd('substr');
}
Рейтинг производительности
Как правило, рейтинг производительности от самого быстрого к самому медленному:
startsWith()(нативная реализация)indexOf() === 0- Сравнение
substr() - Сравнение
substring() - Сравнение
slice()
Полное решение с резервным вариантом
Для решения, готового к использованию в производстве и работающего во всех браузерах, вот комплексный подход:
1. Современный подход с обнаружением возможностей
// Проверяем, доступен ли startsWith, если нет, используем полифил
if (!String.prototype.startsWith) {
// Простой полифил
String.prototype.startsWith = function(searchString, position) {
position = position || 0;
return this.substr(position, searchString.length) === searchString;
};
}
// Использование
var haystack = 'hello world';
var needle = 'he';
console.log(haystack.startsWith(needle)); // true
2. Подход на основе библиотек
// Использование lodash/underscore
_.startsWith(haystack, needle);
// Или использование пользовательской функции утилиты
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. Интеграция с инструментами сборки
Если вы используете инструмент сборки, такой как Webpack, вы можете автоматически включать полифилы:
// webpack.config.js
module.exports = {
// ... другая конфигурация
entry: ['core-js/fn/string/starts-with', './app.js']
};
4. Подход с прогрессивным улучшением
// Определяем startsWith, если он недоступен
if (typeof String.prototype.startsWith !== 'function') {
String.prototype.startsWith = function(searchString, position) {
position = position || 0;
return this.indexOf(searchString, position) === position;
};
}
// Теперь вы можете использовать его везде
var url = 'https://example.com/path';
if (url.startsWith('https://')) {
// Обработка безопасного соединения
}
Источники
- 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
Заключение
Проверка того, начинается ли одна строки с другой в JavaScript, является простой задачей с использованием современного метода startsWith(), введенного в ES6. Для наиболее читаемого и поддерживаемого кода всегда предпочитайте нативный метод startsWith(), когда ваша целевая аудитория использует современные браузеры. Для максимальной совместимости со всеми браузерами, включая более старые, такие как Internet Explorer 11, реализуйте соответствующий полифил или используйте обнаружение возможностей для предоставления резервной функциональности. Альтернативные подходы с использованием indexOf(), substr(), substring() или slice() могут использоваться, когда поддержка ES6 недоступна, хотя они могут быть немного менее производительными, чем нативная реализация. Всегда тщательно тестируйте логику префиксации строк в целевой браузерной среде, чтобы обеспечить согласованное поведение.