我多年来一直在编写Javascript,但刚才意识到我并不完全理解这些“HTML-y”方法实际上是如何与DOM交互的。
我的假设是,当HTML被解释为DOM时,浏览器会保留关于哪个HTML元素成为哪个DOM节点的引用。
因此,对于.getElementById
选择元素时,浏览器会通过引用返回相关节点。那么为什么不做.getNodeById
然后更正确?
我的假设是.innerHTML
在运行时被浏览器解释为DOM。但是,在IE7等旧版浏览器中,.innerHTML
不能用于创建表节点。这告诉我,它最初只是为了修改现有节点的文本属性,但它似乎很奇怪它存在,我们不只是使用.innerText
。
我想我只是对一些Javascript历史感到困惑。
答案 0 :(得分:5)
嗯,问题是,#!/usr/bin/python
import unittest
import sys, os
import json
import string
class MyTestRunner(unittest.TextTestRunner):
def _makeResult(self):
return MyTestResult(self.stream, self.descriptions, self.verbosity)
class MyTestResult(unittest._TextTestResult):
"""
Holder for test result information.
Test results are automatically managed by the TestCase and TestSuite
classes, and do not need to be explicitly manipulated by writers of tests.
Each instance holds the total number of tests run, and collections of
failures and errors that occurred among those test runs. The collections
contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
formatted traceback of the error that occurred.
"""
_previousTestClass = None
_testRunEntered = False
_moduleSetUpFailed = False
def __init__(self, stream=None, descriptions=None, verbosity=None):
self.failfast = False
self.failures = []
self.errors = []
self.testsRun = 0
self.skipped = []
self.expectedFailures = []
self.unexpectedSuccesses = []
self.shouldStop = False
self.buffer = False
self._stdout_buffer = None
self._stderr_buffer = None
self._original_stdout = sys.stdout
self._original_stderr = sys.stderr
self._mirrorOutput = False
# List containing all the run tests, their index and their result. This is the new line of code.
self.tests_run = []
def getTestsReport(self):
"""Returns the run tests as a list of the form [test_description, test_index, result]"""
return self.tests_run
###
### Modified the functions so that we add the test case to the tests run list.
### -1 means Failure. 0 means error. 1 means success.
###
def addError(self, test, err):
"""
Called when an error has occurred. 'err' is a tuple of values as
returned by sys.exc_info().
"""
self.errors.append((test, self._exc_info_to_string(err, test)))
self._mirrorOutput = True
self.tests_run.append([test.shortDescription(), self.testsRun, 0])
TestResult.addError(self, test, err)
def addFailure(self, test, err):
"""
Called when an error has occurred. 'err' is a tuple of values as
returned by sys.exc_info().
"""
self.failures.append((test, self._exc_info_to_string(err, test)))
self._mirrorOutput = True
self.tests_run.append([test.shortDescription(), self.testsRun, -1])
TestResult.addFailure(self, test, err)
def addSuccess(self, test):
"Called when a test has completed successfully"
self.tests_run.append([test.shortDescription(), self.testsRun, 1])
TestResult.addSuccess(self, test)
class MyTest(unittest.TestCase):
currentResult = None # holds last result object passed to run method
results = [] # Holds all results so we can report back to the CCC backend
@classmethod
def setResult(cls, amount, errors, failures, skipped):
cls.amount, cls.errors, cls.failures, cls.skipped = \
amount, errors, failures, skipped
def tearDown(self):
amount = self.currentResult.testsRun
errors = self.currentResult.errors
failures = self.currentResult.failures
skipped = self.currentResult.skipped
self.setResult(amount, errors, failures, skipped)
@classmethod
def tearDownClass(cls):
print json.dumps(
{
'ran': cls.amount,
'errors': len(cls.errors),
'failures': len(cls.failures),
'succeeded': cls.amount - len(cls.errors) - len(cls.failures),
'skipped': len(cls.skipped),
'test_data' : dataHolder.x
},
sort_keys=True, indent=4, separators=(',', ': ')
)
return
def run(self, result=None):
self.currentResult = result # remember result for use in tearDown
unittest.TestCase.run(self, result) # call superclass's run() method
# Tests are defined below.
def test_something(self):
self.assertEqual(1, 2)
if __name__ == '__main__':
module = __import__('__main__')
testRunner = MyTestRunner(verbosity=0)
test = unittest.defaultTestLoader.loadTestsFromModule(module)
print test
test2 = unittest.defaultTestLoader.loadTestsFromNames(test, module)
result = unittest.testRunner.run(test2)
和.innerHTML
之类的东西根本不是JavaScript对象。它们是语言规范所称的"主机对象" - 它是FFI的一种形式。在大多数浏览器中调用.getElementById
时会发生的情况是,字符串从JS字符串编组到DOM字符串,然后传递给C ++代码。
事实上,他们可以提供他们喜欢的任何语义 - 语言不能保证他们的行为方式(对于其他DOM对象,如定时器和XHR也是如此)。
答案 1 :(得分:0)
好吧,如果你真的想了解内部结构,并想深入了解渲染引擎的深洞,我会给你一个开头,指出你的铬的某些源文件:
http://src.chromium.org/viewvc/blink/trunk/Source/core/dom/Element.cpp
你可以找到像innerHTML这样的东西以及它实际上是如何工作的。 (第2425行)
.getElementById()
将解析为与指定ID匹配的文档元素,并将返回对它的引用。
它的某种标识符与原型方法,getter和setter与该元素交互。只要你与innerHTML等方法交互,你就会告诉引擎对元素引用中引用的元素执行该操作。
只是在源代码里面挖掘。你可能会得到一个很好的见解: