dom document object model 文档对象模型
- 浏览器提供给外界的工具 可以让其他的语言修改或者获取文档的内容
- dom树 将文档分成很多节点
- 元素节点 标签
- 属性节点 标签的操作
- 文本节点 标签内的文本内容
- 获取元素节点
- 通过id名获取 getElementById
- 通过class获取 getElementsByClassName 返回一个集合,因为可以重名,可通过[0]获取某一个
- 通过标签名获取 getElementsByTagName
- 通过标签的name属性获取 getElementsByName
- 通过选择器获取querySelector 匹配到的第一个 querySelectorAll 匹配到的集合
- 事件绑定
- 绑定方法
document.querySelector("input").οnkeydοwn=function(){ console.log("1"); } <!-- 给对象增加一个函数属性,可以被覆盖,修改 --> <!-- 或 --> var fun=function(){ console.log(2); } document.querySelector("input").addEventListener("click",fun); <!-- 添加事件监听,不会被覆盖,修改 --> document.querySelector("input").removeEventListener("click",fun);
- ready onload 事件
$(document).ready(function(){ console.log("文档加载完毕") }) <!-- 上下相同 --> $(function(){ console.log("文档加载完毕") }) <!-- 上下相同 --> window.οnlοad=function(){ console.log("文档加载完毕") }
- keydown事件获取键盘码
document.querySelector("input").οnkeydοwn=function(event){ console.log("键盘按下"); }
- mouseover、mouseout、mouseenter、mouseleave事件
- 不论鼠标指针离开被选元素还是任何子元素,都会触发 mouseout 事件。
只有在鼠标指针离开被选元素时,才会触发 mouseleave 事件。 不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件。对应mouseout 只有在鼠标指针穿过被选元素时,才会触发 mouseenter 事件。对应mouseleave,,,坑: mouseout: 会造成反复触发事件, 用mouseleave代替即可
- 不论鼠标指针离开被选元素还是任何子元素,都会触发 mouseout 事件。
- 绑定方法
- event 事件对象
- enent.preventDefault()阻止默认事件
- event.pageX event.pageY 获取距离文档左侧,顶部的鼠标坐标
- event.type 事件类型
- event.keyCode 键盘码
- event.which 按键码
- event.target 鼠标点击的标签
- event.stopPropagation 阻止事件冒泡
- event.timeStamp 文档开启时间,单位为毫秒,下面代码为1秒触发一次
var lastTime = 0; document.querySelector(".btn").onclick = function (event) { var nowTime = event.timeStamp; if (nowTime - lastTime > 1000 || lastTime === 0) { lastTime = nowTime; console.log("111"); } }
- 修改style 修改属性 修改标签内的内容
- 使用 dom元素.style,获取该元素的行内样式表对象,这个对象内的属性可以直接修改
- 使用 setAttribute 修改属性 使用 getAttribute 获得属性的值 使用removeAttribute 删除属性
document.querySelector(".btn").onclick = function () { <!-- 修改style --> document.querySelector(".box").style.backgroundColor = "red"; <!-- 上下相同 下面去掉.加[""] --> document.querySelector(".box").style["background-color"] = "red"; <!-- 修改属性 --> document.querySelector(".box").setAttribute("title", "wosh"); <!-- 修改文本内容 --> document.querySelector(".box").innerText = "aaa"; document.querySelector(".box").innerHTML = "<span>aaa</span>"; <!-- HTML可以识别标签Text不可以 --> <!-- 获取文本内容 --> console.log(document.querySelector(".box").innerText); console.log(document.querySelector(".box").innerHTML); }
- index js默认没有
- 可以通过循环给某个父标签的所有子标签添加index
- dom操作
- element.className获得class
- document.createElement 创建新标签
- element.innerHTML 设置或者返回元素的内容,可包含节点中的子标签以及内容
- element.innerText 设置或者返回元素的内容,不包含节点中的子标签以及内容
- element.setAttribute(attrName,attrValue) 把指定属性设置或更改为指定值。
- element.appendChild(nodeName) 向元素添加新的子节点,作为最后一个子节点,并返回该子节点。如需向 HTML DOM 添加新元素,您首先必须创建该元素 ,然后把它追加到已有的元素上。
- element.insertBefore(insertNode,appointedNode) 在指定的已有的子节点之前插入新节点。
<ul> <li>222</li> </ul> var ul = document.querySelector("ul") var oldLi = document.querySelector("li"); var newLi = document.createElement("li") newLi.innerText = "111" ul.insertBefore(newLi, oldLi);
- this
- 函数内的this的指向:指的是调用该函数的对象
- bind call apply 方法
- bind 生成一个和某个函数一模一样的函数,并且可以修改函数内的this指向,无论什么时候调用该函数this指向基本上不会改变
- 如下bind的指向为obj所以无论给谁添加newFun this的指向都为obj中的a,所以a的值为100.
var a = 10; function fun() { console.log(this.a); } var obj = { a: 100 }; var obj1 = { a: 200 }; var newFun = fun.bind(obj); console.log(newFun); obj1.fun = newFun; obj1.fun();
- call apply 代替某个函数执行,并且将函数内的this指向改了 区别仅限于传参方法 XXFun.call(newThis,参数1,参数2,参数3),,,,,XXFun.apply(newThis,[参数1,参数2,参数3])
- apply 的技巧型 应用 利用 apply 可以替代函数执行并且传参方式换成数组
var arr = [1, 123, 124, 12, 3, 235, 23, 65, 52, 35, 246]; // max 函数操作的时候 没有用到 this 所以无论是什么都可以 var maxNum = Math.max.apply(null, arr); console.log(maxNum);
- 函数
- 第一种声明函数方法享有函数声明提升 fun()可以执行 第二种声明函数方法不享有变量声明提升 x()不可以执行会提示找不到函数
fun(); x(); function fun(){ console.log("1"); } var x = function(){ console.log("2"); }
- argument 拿到所以实参的内容集合 可以argument.length获取数组的长度也可以argument[n]获得对应的内容
function fun() { var sum = 0; for (var i = 0; i < arguments.length; i++) { sum += arguments[i]; } console.log(sum); } fun(1, 2, 3);
- 匿名函数,一般不会自己创建 一般都是当作参数传递,函数后加个括号,立即执行,封装作用域(函数在括号内) 因为全局变量越多就会污染全局环境
(function (){ console.log("1"); })();
- 回调函数,当一个函数被当作参数传递的时候这个函数就是回调函数。
- 递归函数,函数内调用函数本身
- 第一种声明函数方法享有函数声明提升 fun()可以执行 第二种声明函数方法不享有变量声明提升 x()不可以执行会提示找不到函数
- 构造函数, 用于创建对象的函数
- 依然是个函数,函数名首字母必须大写
- 构造函数内部使用 this 指向创建好的对象内添加属性或方法
- 必须有 new 不然 this 指向的会变成 windows
- 构造函数永远一个原型属性 prototype ,该属性是一个对象 这个对象内创建的内容是给所有创建的对象添加一个属性
- 只要是对象内部都会默认有一个 proto 属性,如果这个对象是你的某个构造函数创建出来的话,那么这个 proto 指的就是你的构造西数的原型对象,如果不是那么这个 ptoto 指的就是js内置的构造函数 Object 的原型对象,如果一个对象一直查找 proto 那么最终指向的是null
- 原型内的属性和方法(prototype声明的方法)会在实例化对象下的 proto 属性内显示(该属性指的是创建该实例化对象的构造函数的原型对象);
- 如果原型对象(prototype)修改了公共的原型对象方法也改变了
- 构造函数的原型对象内默认会有一个 constructor 方法,该方法指的是构造函数本身
function CreatCat(name, age) { this.name = name; this.age = age; } CreatCat.prototype.say=function(){ console.log(this.name) } var cat1 = new CreatCat("咪咪", 1) console.log(cat1); cat1.say(); console.log(cat1.constructor);
- 当实例化对象访问或者获取 公共的原型内的方法或者属性的时候 一直会在原型对象内查找 如果原型对象修改了,实例化对象的公共属性和方法也变了(上面的say方法)
- 构造函数的合并
- 普通合并,用 assign 将 user 的方法也合并给 systemuser,但不会改变 systemuser 的原型对象
function User(name, age) { this.name = name; this.age = age; } User.prototype.say = function () { console.log("猫") } var user1 = new User("张三", 18) console.log(user1); function SystemUser(username, userage) { User.call(this, username, userage); } Object.assign(SystemUser.prototype, User.prototype); var systemuser1 = new SystemUser("李四", 23) console.log(systemuser1); SystemUser.prototype.sayHi = function () { console.log('我是管理员') } systemuser1.sayHi(); user1.sayHi();//提示错误
- for in 语句
var obj = { name: '哈哈哈', a: 'hello', age: 20 } var obj1 = { age: 0 } for (var key in obj) { // key 代表属性名 // 当对象的属性名存在了一个变量内 想要访问属性值 obj[变量] // console.log(obj[key]) obj1[key] = obj[key] } console.log(obj1);
- Object.keys(对象)获取对象内的所有属性名集合
var obj = { name: '哈哈哈', a: 'hello', age: 20 } var keys = Object.keys(obj); console.log(keys); var obj1 = { age: 0 } for (var i = 0; i < keys.length; i++) { obj1[keys[i]] = obj[keys[i]] } console.log(obj1);
- 使用高级 js 语法 … 展开运算符
var obj1 = { age: 20 } var obj2 = { name: '哈哈哈' } var obj3 = { say: 'hello' } var obj = { ...obj1, ...obj2, ...obj3 } console.log(obj);
- 另一种继承
function Animal(type) { this.type = type; } Animal.prototype.say = function () { console.log("我是" + this.type + "动物"); } var catAnimal = new Animal("猫科类"); console.log(catAnimal); catAnimal.say(); function Cat(name, age) { this.name = name this.age = age } Cat.prototype = catAnimal var mimi = new Cat('小花儿', 2) mimi.say()
- 普通合并,用 assign 将 user 的方法也合并给 systemuser,但不会改变 systemuser 的原型对象
- 闭包
- 函数内嵌套函数就会形成闭包
- 作用域的嵌套 而且嵌套关系永远存在
- 闭包外层定义的变量会一直存储在内存中,等待闭包内层的作用域访问
- 内存占用比较大
function fun(){ var num = 10; function fun1(){ num++; console.log(num) } return fun1; } var newFun=fun(); newfun(); <!-- 11 --> newfun(); <!-- 12 --> newfun(); <!-- 13 --> fun=null; newFun=null;
- 当前页面有5个button,要求是点击每个button的时候弹出对应的编号
<body> <button>Button0</button> <button>Button1</button> <button>Button2</button> <button>Button3</button> <button>Button4</button> </body> </html> <script> let btnList=document.querySelectorAll('button') for(var i = 0;i<btnList.length;i++){ //使用立刻执行函数 闭包接收i的值 因为异步执行方法会在同步执行方法后执行 (function(i){ btnList[i].onclick = function(){ console.log(i) } })(i); } </script>