bởi Alexey Samoshkin Biết động cơ của bạnNhững điều kỳ lạ có thể xảy ra trong JavaScript[Chỉnh sửa 2/5/2018]: Bài đăng này hiện có sẵn bằng tiếng Nga. Claps to Serj Bulavyk vì những nỗ lực của mình.: This post is now
available in Russian. Claps to Serj Bulavyk for his efforts. Loại ép buộc là quá trình chuyển đổi giá trị từ loại này sang loại khác (chẳng hạn như chuỗi sang số, đối tượng thành boolean, v.v.). Bất kỳ loại nào, có thể là nguyên thủy hoặc một đối tượng, là một đối tượng hợp lệ cho sự ép buộc loại. Để nhớ lại, các nguyên thủy là: số, chuỗi, boolean, null, ký hiệu + không xác định (được thêm vào trong ES6). is the process of converting value from one
type to another (such as string to number, object to boolean, and so on). Any type, be it primitive or an object, is a valid subject for type coercion. To recall, primitives are: number, string, boolean, null, undefined + Symbol (added in ES6). Như một ví dụ về sự ép buộc loại trong thực tế, hãy nhìn vào bảng so sánh JavaScript, cho thấy cách thức của người vận hành bình đẳng lỏng lẻo hoạt động cho các loại String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 2 và String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 3 khác nhau. Ma trận này có vẻ đáng sợ do sự ép buộc loại ngầm mà nhà điều hành String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 1 thực hiện, và nó khó có thể nhớ tất cả các kết hợp đó. Và bạn không phải làm điều đó - chỉ cần học các nguyên tắc ép buộc loại cơ bản. Bài viết này đi sâu về cách ép buộc loại hoạt động trong JavaScript và sẽ giúp bạn có kiến thức cần thiết, vì vậy bạn có thể cảm thấy tự tin giải thích những gì các biểu thức sau đây được tính toán. Đến cuối bài viết, tôi sẽ hiển thị câu trả lời và giải thích chúng. true + false
12 / "6"
"number" + 15 + 3
15 + 3 + "number"
[1] > null
"foo" + + "bar"
'true' == true
false == 'false'
null == ''
!!"false" == !!"true"
[‘x’] == ‘x’
[] + null + 1
[1,2,3] == [1,2,3]
{}+[]+{}+[1]
!+[]+[]+![]
new Date(0) - 0
new Date(0) + 0
Vâng, danh sách này có đầy đủ những điều khá ngớ ngẩn bạn có thể làm với tư cách là một nhà phát triển. Trong 90% các trường hợp sử dụng, tốt hơn là tránh bị ép buộc loại ngầm. Hãy coi danh sách này là một bài tập học tập để kiểm tra kiến thức của bạn về cách thức cưỡng chế loại hoạt động. Nếu bạn chán, bạn có thể tìm thấy nhiều ví dụ hơn về wtfjs.com. Nhân tiện, đôi khi bạn có thể phải đối mặt với những câu hỏi như vậy trong cuộc phỏng vấn cho vị trí nhà phát triển JavaScript. Vì vậy, tiếp tục đọc? In ngầm so với sự ép buộc rõ ràngLoại cưỡng chế có thể rõ ràng và tiềm ẩn. Khi một nhà phát triển thể hiện ý định chuyển đổi giữa các loại bằng cách viết mã thích hợp, như String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 5, nó được gọi là ép buộc loại rõ ràng (hoặc loại đúc).explicit type coercion (or type casting).Vì JavaScript là ngôn ngữ được gõ yếu, các giá trị cũng có thể được chuyển đổi giữa các loại khác nhau một cách tự động và nó được gọi là ép buộc loại ngầm. Nó thường xảy ra khi bạn áp dụng các toán tử vào các giá trị của các loại khác nhau, như ____36, String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 7, String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 8 hoặc nó có thể được kích hoạt bởi bối cảnh xung quanh, như với String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 9, trong đó Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 0 bị ép buộc để boolean.implicit
type coercion. It usually happens when you apply operators to values of different types, like
String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 6, String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 7, String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 8, or it can be triggered by the surrounding context, like with String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 9, where Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 0 is coerced to boolean.Một toán tử không kích hoạt sự ép buộc loại ngầm là Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 1, được gọi là toán tử bình đẳng nghiêm ngặt. Mặt khác, toán tử bình đẳng lỏng lẻo String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 1 thực hiện cả so sánh và ép buộc loại nếu cần.Sự ép buộc loại ẩn là một thanh kiếm hai cạnh: nó là một nguồn thất vọng và khuyết tật tuyệt vời, nhưng cũng là một cơ chế hữu ích cho phép chúng ta viết ít mã hơn mà không mất khả năng đọc. Ba loại chuyển đổiQuy tắc đầu tiên cần biết là chỉ có ba loại chuyển đổi trong JavaScript: Thứ hai, logic chuyển đổi cho các nguyên thủy và đối tượng hoạt động khác nhau, nhưng cả nguyên thủy và đối tượng chỉ có thể được chuyển đổi theo ba cách đó. Hãy bắt đầu với những người nguyên thủy đầu tiên. Chuyển đổi chuỗiĐể chuyển đổi rõ ràng các giá trị thành một chuỗi, hãy áp dụng hàm Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 3. Sự ép buộc ngầm được kích hoạt bởi toán tử nhị phân Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 4, khi bất kỳ toán hạng nào là một chuỗi:String(123) // explicit
123 + '' // implicit
Tất cả các giá trị nguyên thủy được chuyển đổi thành các chuỗi một cách tự nhiên như bạn mong đợi: String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false'
Chuyển đổi biểu tượng là một chút khó khăn, bởi vì nó chỉ có thể được chuyển đổi một cách rõ ràng, nhưng không ngầm. Đọc thêm về các quy tắc cưỡng chế Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 5.String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown
Chuyển đổi BooleanĐể chuyển đổi một cách rõ ràng một giá trị thành boolean, hãy áp dụng hàm Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 6. Chuyển đổi quan trọng xảy ra trong bối cảnh logic hoặc được kích hoạt bởi các toán tử logic (Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 7 Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 8 Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 9). Implicit conversion happens in logical context, or is triggered by logical operators ( Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 7 Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 8 Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 9) .Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator
Lưu ý: Các toán tử logic như Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 7 và Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 8 không chuyển đổi boolean trong nội bộ, nhưng thực sự trả về giá trị của các toán hạng gốc, ngay cả khi chúng không boolean.: Logical operators such as Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 7
and Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 8 do boolean conversions internally, but actually return the value of original operands, even if they are not boolean.// returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123
Ngay khi chỉ có 2 kết quả chuyển đổi Boolean: // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 2 hoặc // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 3, nó chỉ dễ nhớ hơn trong danh sách các giá trị giả.Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false
Bất kỳ giá trị nào không có trong danh sách đều được chuyển đổi thành // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 2, bao gồm đối tượng, chức năng, // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 5, // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 6, loại do người dùng xác định, v.v. Biểu tượng là giá trị sự thật. Đối tượng trống và mảng cũng là giá trị sự thật:Boolean({}) // true
Boolean([]) // true
Boolean(Symbol()) // true
!!Symbol() // true
Boolean(function() {}) // true
Chuyển đổi sốĐể chuyển đổi rõ ràng, chỉ cần áp dụng hàm // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 7, giống như bạn đã làm với Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 6 và Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 3.Chuyển đổi ngầm là khó khăn, bởi vì nó đã được kích hoạt trong nhiều trường hợp hơn: - Các toán tử so sánh (
Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false 0, Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false 1, ________ 62, ________ 63) - Các toán tử bitwise (
Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false 4 Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false 5 Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false 6 Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false 7) - toán tử số học (
Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false 8 Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 4 Boolean({}) // true
Boolean([]) // true
Boolean(Symbol()) // true
!!Symbol() // true
Boolean(function() {}) // true 0 Boolean({}) // true
Boolean([]) // true
Boolean(Symbol()) // true
!!Symbol() // true
Boolean(function() {}) // true 1 Boolean({}) // true
Boolean([]) // true
Boolean(Symbol()) // true
!!Symbol() // true
Boolean(function() {}) // true 2). Lưu ý rằng BinaryBoolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 4 không kích hoạt chuyển đổi số, khi bất kỳ toán hạng nào là một chuỗi. - Nhà điều hành
Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 4 - toán tử bình đẳng lỏng lẻo
String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 1 (bao gồm Boolean({}) // true
Boolean([]) // true
Boolean(Symbol()) // true
!!Symbol() // true
Boolean(function() {}) // true 6). Lưu ý rằng String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 1 không kích hoạt chuyển đổi số khi cả hai toán hạng là chuỗi. Note that String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 1 does not trigger numeric conversion when both operands are strings.
Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit
Dưới đây là cách các giá trị nguyên thủy được chuyển đổi thành số: Number(null) // 0
Number(undefined) // NaN
Number(true) // 1
Number(false) // 0
Number(" 12 ") // 12
Number("-12.34") // -12.34
Number("\n") // 0
Number(" 12s ") // NaN
Number(123) // 123
Khi chuyển đổi một chuỗi thành một số, công cụ đầu tiên cắt các ký tự dẫn và kéo theo, Boolean({}) // true
Boolean([]) // true
Boolean(Symbol()) // true
!!Symbol() // true
Boolean(function() {}) // true 8, Boolean({}) // true
Boolean([]) // true
Boolean(Symbol()) // true
!!Symbol() // true
Boolean(function() {}) // true 9 ký tự, trả về Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 0 nếu chuỗi được cắt không đại diện cho một số hợp lệ. Nếu chuỗi trống, nó sẽ trả về Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 1.Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 2 và Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 3 được xử lý khác nhau: Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 2 trở thành Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 1, trong khi Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 3 trở thành Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 0.Các biểu tượng không thể được chuyển đổi thành một số không rõ ràng cũng không ngầm. Hơn nữa, Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 8 bị ném, thay vì âm thầm chuyển đổi thành Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 0, giống như nó xảy ra với Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 3. Xem thêm về các quy tắc chuyển đổi biểu tượng trên MDN.String(123) // explicit
123 + '' // implicit 0Có hai quy tắc đặc biệt cần nhớ:special rules to remember: - Khi áp dụng
String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 1 lên Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 2 hoặc Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 3, chuyển đổi số không xảy ra. Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 2 chỉ bằng với Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 2 hoặc Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 3 và không bằng bất cứ thứ gì khác.
String(123) // explicit
123 + '' // implicit 12. Nan không bằng bất cứ thứ gì ngay cả chính nó: String(123) // explicit
123 + '' // implicit 2Loại cưỡng chế cho các đối tượngCho đến nay, chúng tôi đã xem xét sự ép buộc loại cho các giá trị nguyên thủy. Điều đó không thú vị lắm. Khi nói đến các đối tượng và các biểu thức gặp phải động cơ như Number(null) // 0
Number(undefined) // NaN
Number(true) // 1
Number(false) // 0
Number(" 12 ") // 12
Number("-12.34") // -12.34
Number("\n") // 0
Number(" 12s ") // NaN
Number(123) // 123 7, trước tiên nó cần chuyển đổi một đối tượng thành giá trị nguyên thủy, sau đó được chuyển đổi thành loại cuối cùng. Và vẫn chỉ có ba loại chuyển đổi: số, chuỗi và boolean.Trường hợp đơn giản nhất là chuyển đổi Boolean: bất kỳ giá trị không định tuyến nào luôn bị ép buộc thành // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 2, bất kể đối tượng hay mảng có trống hay không. coerced to // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 2, no matter if an object or an array is empty or not.Các đối tượng được chuyển đổi thành nguyên thủy thông qua phương thức Number(null) // 0
Number(undefined) // NaN
Number(true) // 1
Number(false) // 0
Number(" 12 ") // 12
Number("-12.34") // -12.34
Number("\n") // 0
Number(" 12s ") // NaN
Number(123) // 123 9 nội bộ, chịu trách nhiệm cho cả chuyển đổi số và chuỗi.Dưới đây là việc triển khai giả của phương thức Number(null) // 0
Number(undefined) // NaN
Number(true) // 1
Number(false) // 0
Number(" 12 ") // 12
Number("-12.34") // -12.34
Number("\n") // 0
Number(" 12s ") // NaN
Number(123) // 123 9:Number(null) // 0
Number(undefined) // NaN
Number(true) // 1
Number(false) // 0
Number(" 12 ") // 12
Number("-12.34") // -12.34
Number("\n") // 0
Number(" 12s ") // NaN
Number(123) // 123 9 được truyền với giá trị đầu vào và loại chuyển đổi ưa thích: String(123) // explicit
123 + '' // implicit 02 hoặc String(123) // explicit
123 + '' // implicit 03. String(123) // explicit
123 + '' // implicit 04 là tùy chọn.Cả chuyển đổi số và chuỗi đều sử dụng hai phương thức của đối tượng đầu vào: String(123) // explicit
123 + '' // implicit 05 và String(123) // explicit
123 + '' // implicit 06. Cả hai phương pháp đều được khai báo trên String(123) // explicit
123 + '' // implicit 07 và do đó có sẵn cho bất kỳ loại dẫn xuất nào, chẳng hạn như // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 6, // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 5, v.v.Nói chung, thuật toán như sau: - Nếu đầu vào đã là một nguyên thủy, không làm gì và trả lại nó.
2. Gọi String(123) // explicit
123 + '' // implicit 10, nếu kết quả là nguyên thủy, hãy trả lại.3. Gọi String(123) // explicit
123 + '' // implicit 11, nếu kết quả là nguyên thủy, hãy trả lại.4. Nếu cả String(123) // explicit
123 + '' // implicit 10 và String(123) // explicit
123 + '' // implicit 11 không mang lại nguyên thủy, hãy ném Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 8.Chuyển đổi số đầu tiên gọi String(123) // explicit
123 + '' // implicit 05 (3) với dự phòng với String(123) // explicit
123 + '' // implicit 06 (2). Chuyển đổi chuỗi thực hiện ngược lại: String(123) // explicit
123 + '' // implicit 06 (2) theo sau là String(123) // explicit
123 + '' // implicit 05 (3).Hầu hết các loại tích hợp không có String(123) // explicit
123 + '' // implicit 05 hoặc có String(123) // explicit
123 + '' // implicit 05 trả về chính đối tượng String(123) // explicit
123 + '' // implicit 21, do đó, nó đã bỏ qua vì nó không phải là nguyên thủy. Đó là lý do tại sao chuyển đổi số và chuỗi có thể hoạt động giống nhau - cả hai đều gọi String(123) // explicit
123 + '' // implicit 22.Các toán tử khác nhau có thể kích hoạt chuyển đổi số hoặc chuỗi với trợ giúp của tham số String(123) // explicit
123 + '' // implicit 04. Nhưng có hai ngoại lệ: Bình đẳng lỏng lẻo String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 1 và các toán tử Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 4 kích hoạt các chế độ chuyển đổi mặc định (String(123) // explicit
123 + '' // implicit 04 không được chỉ định hoặc bằng với String(123) // explicit
123 + '' // implicit 27). Trong trường hợp này, hầu hết các loại tích hợp đều giả định chuyển đổi số là mặc định, ngoại trừ // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 6 không chuyển đổi chuỗi.Dưới đây là một ví dụ về hành vi chuyển đổi // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 6:Bạn có thể ghi đè các phương thức String(123) // explicit
123 + '' // implicit 22 và String(123) // explicit
123 + '' // implicit 31 mặc định để nối vào logic chuyển đổi đối tượng sang nguyên tắc.Lưu ý cách String(123) // explicit
123 + '' // implicit 32 trả về String(123) // explicit
123 + '' // implicit 33 dưới dạng chuỗi. Toán tử Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 4 kích hoạt chế độ chuyển đổi mặc định và như đã nói trước String(123) // explicit
123 + '' // implicit 35 giả sử chuyển đổi số làm mặc định, do đó sử dụng phương thức String(123) // explicit
123 + '' // implicit 31 trước tiên thay vì String(123) // explicit
123 + '' // implicit 22.Biểu tượng ES6.Toprimitive Phương phápTrong ES5, bạn có thể nối vào logic chuyển đổi đối tượng sang nguyên bản bằng cách ghi đè các phương thức String(123) // explicit
123 + '' // implicit 06 và String(123) // explicit
123 + '' // implicit 05.Trong ES6, bạn có thể đi xa hơn và thay thế hoàn toàn thói quen nội bộ bằng cách thực hiện phương thức ____141 trên một đối tượng. Ví dụĐược trang bị lý thuyết, bây giờ hãy để Lừa quay lại các ví dụ của chúng tôi: String(123) // explicit
123 + '' // implicit 3Dưới đây bạn có thể tìm thấy lời giải thích cho mỗi biểu thức. Nhà điều hành nhị phân Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 4 kích hoạt chuyển đổi số cho // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 2 và // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 3String(123) // explicit
123 + '' // implicit 4Toán tử phân chia số học Boolean({}) // true
Boolean([]) // true
Boolean(Symbol()) // true
!!Symbol() // true
Boolean(function() {}) // true 1 kích hoạt chuyển đổi số cho chuỗi String(123) // explicit
123 + '' // implicit 46:String(123) // explicit
123 + '' // implicit 5Nhà điều hành Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 4 có tính kết hợp từ trái sang phải, vì vậy biểu thức String(123) // explicit
123 + '' // implicit 48 chạy trước. Vì một toán hạng là một chuỗi, toán tử Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 4 kích hoạt chuyển đổi chuỗi cho số String(123) // explicit
123 + '' // implicit 50. Trên biểu thức bước thứ hai String(123) // explicit
123 + '' // implicit 51 được đánh giá tương tự.String(123) // explicit
123 + '' // implicit 6Biểu thức String(123) // explicit
123 + '' // implicit 52 được đánh giá đầu tiên. Không cần sự ép buộc nào cả, vì cả hai toán hạng là số. Trên bước thứ hai, biểu thức String(123) // explicit
123 + '' // implicit 53 được đánh giá và vì một toán hạng là một chuỗi, nó kích hoạt chuyển đổi chuỗi.String(123) // explicit
123 + '' // implicit 7Nhà điều hành so sánh Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false 5GT; Kích hoạt chuyển đổi số f ________ 155 [1] AString(123) // explicit
123 + '' // implicit 56ULL.String(123) // explicit
123 + '' // implicit 8Toán tử Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 4 không được ưu tiên cao hơn toán tử Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 4 nhị phân. Vì vậy, biểu thức String(123) // explicit
123 + '' // implicit 59 đánh giá đầu tiên. Unary Plus kích hoạt chuyển đổi số cho chuỗi String(123) // explicit
123 + '' // implicit 60. Vì chuỗi không đại diện cho một số hợp lệ, kết quả là Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 0. Trên bước thứ hai, biểu thức String(123) // explicit
123 + '' // implicit 62 được đánh giá.String(123) // explicit
123 + '' // implicit 9String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 1 Toán tử kích hoạt chuyển đổi số, chuỗi String(123) // explicit
123 + '' // implicit 64 được chuyển đổi thành NAN, Boolean // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 2 được chuyển đổi thành 1.String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false' 0String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 1 thường kích hoạt chuyển đổi số, nhưng nó không phải là trường hợp với Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 2. Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 2 chỉ bằng với Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 2 hoặc Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 3 và không bằng bất cứ thứ gì khác.String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false' 1String(123) // explicit
123 + '' // implicit 71 toán tử chuyển đổi cả chuỗi String(123) // explicit
123 + '' // implicit 64 và String(123) // explicit
123 + '' // implicit 73 thành boolean // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 2, vì chúng là các chuỗi không trống. Sau đó, String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 1 chỉ kiểm tra sự bình đẳng của hai boolean String(123) // explicit
123 + '' // implicit 76 mà không có bất kỳ sự ép buộc nào.String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false' 2String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 1 toán tử kích hoạt chuyển đổi số cho một mảng. Phương thức Array Array String(123) // explicit
123 + '' // implicit 31 trả về chính mảng và bị bỏ qua bởi vì nó không phải là nguyên thủy. Array Array String(123) // explicit
123 + '' // implicit 22 chuyển đổi String(123) // explicit
123 + '' // implicit 80 thành chuỗi String(123) // explicit
123 + '' // implicit 81.String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false' 3Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 4 Toán tử kích hoạt chuyển đổi số cho String(123) // explicit
123 + '' // implicit 83. Phương pháp Array Array String(123) // explicit
123 + '' // implicit 31 bị bỏ qua, bởi vì nó tự trả về Array, không nguyên thủy. Array Array String(123) // explicit
123 + '' // implicit 06 trả về một chuỗi trống.Trên biểu thức bước thứ hai String(123) // explicit
123 + '' // implicit 86 được đánh giá.String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false' 4Logic Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 7 và Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 8 Các nhà khai thác ép buộc các toán tử để boolean, nhưng trả lại các toán hạng gốc (không phải booleans). Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 1 là giả, trong khi String(123) // explicit
123 + '' // implicit 90 là sự thật, bởi vì nó là một chuỗi không trống. String(123) // explicit
123 + '' // implicit 91 Đối tượng trống cũng là sự thật.String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false' 5Không cần ép buộc vì cả hai toán hạng đều có cùng loại. Vì String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 1 kiểm tra nhận dạng đối tượng (và không phải cho bình đẳng đối tượng) và hai mảng là hai trường hợp khác nhau, kết quả là // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 3.String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false' 6Tất cả các toán hạng là các giá trị không nguyên thủy, do đó Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 4 bắt đầu với chuyển đổi số kích hoạt ngoài cùng bên trái. Cả hai phương thức String(123) // explicit
123 + '' // implicit 95 và String(123) // explicit
123 + '' // implicit 96 String(123) // explicit
123 + '' // implicit 05 tự trả về chính đối tượng, do đó, nó đã bỏ qua. String(123) // explicit
123 + '' // implicit 22 được sử dụng như một dự phòng. Bí quyết ở đây là String(123) // explicit
123 + '' // implicit 91 đầu tiên không được coi là một đối tượng theo nghĩa đen, mà là một tuyên bố khai báo khối, do đó, nó đã bỏ qua. Đánh giá bắt đầu bằng biểu thức String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false' 00 tiếp theo, được chuyển đổi thành một chuỗi trống thông qua phương thức String(123) // explicit
123 + '' // implicit 22 và sau đó thành Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit 1.String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false' 7Điều này được giải thích tốt hơn từng bước theo ưu tiên của nhà điều hành. String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false' 8Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false 8 Người vận hành kích hoạt chuyển đổi số cho // returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123 6. String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false' 05 Trả về số mili giây kể từ thời đại UNIX.String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false' 9Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator 4 Trình kích hoạt toán tử chuyển đổi mặc định. Ngày giả định chuyển đổi chuỗi là một mặc định, do đó, phương thức String(123) // explicit
123 + '' // implicit 22 được sử dụng, thay vì String(123) // explicit
123 + '' // implicit 31.String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown 0Tài nguyênTôi thực sự muốn giới thiệu cuốn sách xuất sắc của Hiểu về es6, được viết bởi Nicholas C. Zakas. Nó có một tài nguyên học tập ES6 tuyệt vời, không quá cao và không đào sâu vào nội bộ quá nhiều. Và đây là một cuốn sách hay về ES5 - nói các bài nói được viết bởi Axel Rauschmayer. (Nga) Đặc biệt là hai trang này về cưỡng chế loại.Russian) Современный учебник Javascript — https://learn.javascript.ru/. Especially these
two pages on type coercion. Bảng so sánh JavaScript-https://dorey.github.io/javascript-equality-Table/ WTFJS - Một blog nhỏ về ngôn ngữ mà chúng tôi yêu thích mặc dù cho chúng tôi rất nhiều để ghét - https://wtfjs.com/
Học mã miễn phí. Chương trình giảng dạy nguồn mở của Freecodecamp đã giúp hơn 40.000 người có được việc làm với tư cách là nhà phát triển. Bắt đầu
JavaScript có chuyển đổi loại tự động không?
Khi một toán tử đang được sử dụng bởi một loại không chính xác, JavaScript sẽ chuyển đổi giá trị đó thành loại cần thực hiện tính toán.Điều này được gọi là ép buộc loại.. This is called type coercion.
Loại cưỡng chế loại trong JavaScript là gì?
Loại cưỡng chế là chuyển đổi tự động hoặc ẩn các giá trị từ loại dữ liệu này sang loại dữ liệu khác (chẳng hạn như chuỗi thành số).the automatic or implicit conversion of values from one data type to another (such as strings to numbers).
JavaScript có hỗ trợ chuyển đổi loại ngầm không?
Trong một số tình huống nhất định, JavaScript tự động chuyển đổi một loại dữ liệu sang loại khác (sang đúng loại).Điều này được gọi là chuyển đổi ngầm.JavaScript automatically converts one data type to another (to the right type). This is known as implicit conversion.
Liệu JavaScript hỗ trợ loại đúc?
Trong JavaScript, việc đúc loại chỉ có thể được thực hiện cho các chuỗi, số và các loại dữ liệu boolean (đối tượng).Ví dụ về việc đúc loại rõ ràng là các phương thức parseInt (), parseFloat () và toString ().Hàm parseInt () chuyển đổi đối số đầu tiên của nó thành một chuỗi, phân tích chuỗi đó, sau đó trả về một số nguyên hoặc nan.the type casting can be done only for strings, numbers and Boolean (object) data types. Examples of the explicit type casting are methods parseInt(), parseFloat() and toString(). The parseInt() function converts its first argument to a string, parses that string, then returns an integer or NaN. |