这是到目前为止的学习记录,持续更新中
JavaSprit学习笔记
出现背景
网景公司和sun公司合作,由Brendan Eich花费十天设计(敷衍设计的)
- 要求:和java相似,比java简单
- 于是Brendan Eich借鉴了
- c语言的基本语法
- java的数据类型和内存管理
- Scheme的函数“第一等公民”的地位
- Self的基于原型的继承机制
- 总之,js
- 是简化的函数式编程
- 是简化的面向对象编程
- 不是一个非常完善的语言
- 后来,随着不断的使用,开发,完善,js现在已经是以一个成熟的网页编程语言
js的组成
- BOM
- Browser Object Model
- js操作浏览器发生变化的属性和方法
- DOM
- Document Object Model
- js操作文档流发生变化的属性和方法
- ECMAScript
- js的书写规则
- js的语法规则
- 用这种规则来操作BOM、DOM使网页或浏览器的内容发生变化
js的书写位置
- 行内式
写到html标签内部
<a href="" javasprict:'你的js代码';></a>
- 内嵌式
写到html为js准备的标签script里
<script> 你的js代码 </script>
- 外链式
写到一个单独的js文件里,通过标签script的src属性(路径)来链接html文件
<script src="/js/index.js"></script>
不需要依赖任何行为,打开html就可以执行
js的变量
变量
- 在程序的运行过程中,保存一个中间值使用
如何设置变量
var num = 100
- var - 表示准备一个容器
- num - 变量名
- = - 把100保存到num里,不是等于的意思
- 100 - 要存放的数据
一个变量只有一个值,第二次赋值会丢掉第一次的数据。
var num = 100 num = 200
- 此时,num里的数据是200。100就不见/丢掉了
变量的命名规则
- 可以由:数字、字母、下划线、美元符组成
- 不能以数字开头
- 不能是js里的关键字
- var、 function、 for
- 严格区分大小写
- num、NUM、Num是三个不一样的变量
- 最好使用有意义的英文单词,拼音(不许缩写!其他人不理解)
- 可以直观体现这个变量里面保存了什么
如何书写注释
- 注释
- 运行中会自动忽略的内容,主要用于学习沟通,便于理解代码使用
- 书写方法
单行注释
//这是一行注释
多行注释
/* 1 2 3 */
在浏览器输出
alert()
- 弹窗显示
console.log()
- 控制台打印
document.write()
- 直接在页面输出
js的数据类型
基本数据类型
数值类型
- 0x100 - 16进制
- 0o100 - 8进制
- 0b100 - 2进制
字符串类型
var a = "英文状态下引号" var b = '单双引号都可以' var c = "前后引号要配套"
布尔类型
var a = true var b = false //true和false要记牢
空类型
var a //undefined var b = null //null
- undefined - 没有值,没有赋值
- null - 有值,是空值null
引用数据类型
- 盲区
js数据类型检测
tepoof 要检测的变量名
- var a = 100
- var result = tepoof a
- console.log(result)
- number
js数据类型的转换
转数值
- Number()
- 只有全是数字时可以转换
- ParseInt()
- 一位一位查看,到第一个非数字停止,保留前面的数字部分(首位不是数字,返回NaN)
- 只能转整数
- ParseFloat()
- 规则和parseint()一样
- 能转小数
转字符串
- string()
- Tostring()
- 要转换的内容.Tostring()
转布尔
- 要转换的内容.Tostring()
- boolean()
- 要转换的内容.boolean()
- 只有0、NaN、””、undefind、null会被转换成false
- 其他内容全部是true
js的运算符
算数运算符
- +:加法运算
- 只要符号有任何一边是字符串的时候,会进行字符串拼接
- -:减法运算
- *:乘法运算
- /:除法运算
- %:取余运算
赋值运算符
- =:进行赋值操作
- +=
- a += 10(a = a + 10)
- -=
- *=
- /=
- %=
比较运算符
结果一定是个布尔值
- ‘<’
- ‘>’
- ‘<=’
- ‘>=’
- ‘==’
- 等于
- 只比较值是否相等,不比较数据类型
- ‘===’
- 全等于
- 数据类型和值要全部相等
- ‘!=’
- 不等于
- 只考虑值是不是不相等,不考虑数据类型
- ‘!==’
- 不全等
- 数据类型和值任意一个不相等,就是true
逻辑运算符
- && 与
- 两边都为true,最终结果才是true
- || 或
- 两边任意一边是true,最终结果就是true
- ! 非
- 取反运算 !true=false !false=true
自增自减运算符
- ++
- 前置++,先把变量值改变,再用改变后的值参与运算
- 后置++,先参与运算,再改变变量值
- –
- 前置–,先把变量值改变,再用改变后的值参与运算
- 后置–,先参与运算,再改变变量值
条件语句
条件分支语句
if 条件语句
- if(){}
- if(){}else{}
- if(){}else if(){}
- if(){}else if(){}else{}
swith 条件语句
swith(已知条件){
case 选项:
代码
break
case 选项:
代码
break
case 选项:
代码
break
}
找到和已知条件完全匹配的选项执行
需要写break,不然会向下穿透
可以书写一个default,会在所有选项都不匹配的时候执行
当发生穿透时,会从第一个满足条件的选项开始向下穿透
js循环结构语句
主要功能,可以提供一组有规律的数字
while 循环
- while(条件判断){代码段}
- while会重复执行一段代码,直到重复结束才会继续执行后面的代码
- 千万要书写改变初始值的代码,不然就会出现死循环
- 在循环内,初始值,条件判断和改变初始值都能控制循环的次数
- 在循环内,循环控制变量是一组有规律的数字
do while 循环
- do{代码端} while(条件判断)
- 当初始值在条件以内的时候,while和do while是一样的
- 当初始值在条件以外的时候
- while循环一次都不执行
- do while循环会执行一次
for 循环
- for(定义初始值;条件判断;改变初始值){代码}
- 定义初定值
- 进行条件判断
- 执行代码
- 改变初始值
- 优点:防止忘记写改变初始值进入死循环,因为不写“改变初始值”代码会报错
函数
1 | //定义阶段 |
定义函数阶段
- 函数定义阶段,函数体内的代码不执行
函数调用阶段
- 调用一次执行一次
参数
- 形参:
- 就是定义再函数内部使用的变量
- 实参:
- 就是函数调用时给形参赋值的内容
- return
- 在函数内使用return给函数添加一个结果作为函数的返回值
作用域
范围
- 全局作用域
- 一个页面就是一个全局作用域
- 私有作用域
- 只有函数生成私有作用域
使用
- 定义
- 声明在什么位置的变量就是哪一个作用域的变量
- 访问
- 自己有用自己的,自己没有用父级的,以此类推,到全局没有就报错
- 赋值
- 自己给自己的赋值,自己没有的就给父级赋值,以此类推,到全局都没有,定义为全局再赋值
递归函数
一个函数调用了它自身,这种现象就称为递归。
1 | fuction fn(n){ |
但是,一个函数调用了它自身,并设置了结束条件,这个函数才是一个正确的递归函数
1 | fuction fn(n){ |
斐波那契数列
1 | fuction fn(n){ |
数据类型
对象数据类型(Object)
创建
1 | var obj = {hair:'3',eyes:'2'} |
操作
- 增 对象名.键=值 or 对象名[‘键’]=值
- 删 delete 对象名.键 or delete 对象名[‘键’]
- 改 对象名.键=值 or 对象名[‘键’]=值
- 查 对象名.键 or 对象名[‘键’]
数据数据类型(array)
数组:有序的数据集合
- 创建
1
var arr =[100,200,300,400]
- 排列
- 索引:从0开始,依次+1
- 长度操作
- 访问:数组.length
- 设置:数组.length=数字
- 数据操作
- 访问:数组[索引]
- 设置:数组[索引]=值
遍历
- 利用循环进行遍历,开始为0,结束为“小于索引长度”,步长为1,使用循环控制变量当作索引来访问数组里面的每一个数据
1
2
3
4
5var arr = []
for(var i = 0 ; i < arr.length ; i++){
arr[i] //当前索引上存在的数据
}
排序
冒泡排序
选择排序
方法
数组常用方法
帮助我们对数组进行快速操作
- push() 从后面追加
- 语法: 数组.push(数据)
- 作用:将数据追加到数组末尾
- 返回值:追加数据后数组的最新长度
- pop() 从后面删除
- 语法:数组.pop()
- 作用:删除数组的最后一个数据
- 返回值:被删除的数据
- unshift() 从前面添加
- 语法: 数组.unshift(数据)
- 作用: 将数据添加到数组最前
- 返回值: 添加数据后数组的最新长度
- shift() 从前面删除
- 语法:数组.shift()
- 作用: 删除数组最前一个数据
- 返回值: 被删除的数据
- reverse() 反转数组
- 语法: 数组.reverse()
- 作用: 将数组反转
- 返回值:反转后的数组
- splice()
- 语法:数组.splice(开始索引,多少个,要插入的数据)
- 开始索引:默认是0
- 多少个:默认是0
- 要插入的数据: 默认是没有
- 作用:删除数组中若干数据,并选择是否插入新的数据
- 返回值:以新数组的形式返回被删除的数据
- 语法:数组.splice(开始索引,多少个,要插入的数据)
- sort() 数组排序(分类)
- 语法:数组.sort()
- 数组.sort(fuction(a,b){return a - b })
- 数组.sort(fuction(a,b){return b - a })
- 作用:将数组进行排序
- 返回值:排序好的新数组
- 语法:数组.sort()
- join() 数组链接为字符串
- 语法:数组.join(连接符)
- 作用:将数组用连接符连接成为一个字符串
- 返回值:连接好的字符串
- concat() 拼接数组
- 语法:数组.concat(其他数组)
- 作用:将其他数组和数组拼接在一起
- 返回值:拼接好的新数组
- slice() 截取数组
- 语法:数组.slice(开始索引,结束索引)
- 开始索引: 默认是0
- 结束索引: 默认是数组长度
- 作用:截取数组中的某些数据
- 返回值:以新数组的形式返回截取出来的数据
slice(1,3)包前不包后,就说,截取的数据只有索引为1,2的,没有3.
- 语法:数组.slice(开始索引,结束索引)
- indexOf() 查找数据在数组中的索引
- 语法:数组.indexOf(数据)
- 作用:查找数据在数组中索引的位置
- 返回值:
- 有该数据,返回一次出现的索引的位置
- 没有数据,返回-1
item 数组的每一项
index 数组的索引
arr 原始数组
- forEach() 遍历数组
- 语法:数组.forEach(fuction(item,index,arr){})
- 作用:遍历数组
- 返回值:无
- map() 映射数组
- 语法:数组.map(fuction(item,index,arr){})
- 作用:映射数组
- 返回值:映射后的新数组
- filter() 过滤数组
- 语法:数组.filter(fuction(item,index,arr){})
- 作用:过滤数组
- 返回值:过滤后的新数组
- every() 判断是否全部满足条件
- 语法:数组.every(fuction(item,index,arr){})
- 作用:判断数组是不是每一项都满足条件
- 返回值:一个布尔值
- some() 判断是否有满足条件的项
- 语法:数组.some(fuction(item,index,arr){})
- 作用:判断数组是不是有某一项满足条件
- 返回值:一个布尔值
字符串常用方法
帮助我们对字符串进行快速操作
- charAt() 按照索引获取字符
- 语法:字符串.charAt(索引)
- 作用:获取对应索引位置的字符
- 返回值:对应索引位置的字符
- toLowerCase() 转大写
- 语法:字符串.toLowerCase()
- 作用:将字符串内的字母全部转换成小写
- 返回值:转换好的字符串
- toUpperCase() 转小写
- 语法:字符串.toLowerCase()
- 作用: 将字符串内的字母全部转换成大写
- 返回值:转换好的字符串
- replace() 替换字符串
- 语法:字符串.replace(换下内容,换上内容)
- 作用:将字符串内第一个满足换下内容的片段替换成换上内容
- 返回值:替换好的字符串
- trim() 去除首尾空额
- 语法:字符串.trim()
- 作用:去除字符串首尾的空格
- 返回值:去除空格后的字符串
- split() 切割字符串
- 语法:字符串.split(分隔符)
- 作用:按照分隔符将字符串切割成为一个数组
- 返回值:切割后的数组
- substr() 截取字符串
- 语法:字符串.substr(开始索引,多少个)
- 作用:截取字符串
- 返回值:截取出来的字符串
- substring() 截取字符串
- 语法:字符串.substring(开始索引,结束索引)
- 作用:截取字符串
- 返回值:截取出来的字符串
- slice() 截取字符串
- 语法:字符串.slice(开始索引,结束索引)
- 作用:截取字符串
- 返回值:截取出来的字符串
数字常用方法
帮助我们对数字进行快速操作
- random() 0-1之间的随机小数
- 语法:Math.random()
- 作用:获取0-1之间的随机小数。包括0,不包括1.
- 返回值:0-1之间的随机小数
- round() 四舍五入取整
- 语法:Math.round(数字)
- 作用:对数字进行四舍五入取整
- 返回值:四舍五入后的整数
- ceil() 向上取整
- 语法:Math.ceil(数字)
- 作用:对数字进行向上取整
- 返回值:向上取整后的整数
- floor() 向下取整
- 语法:Math.floor(数字)
- 作用:对数字进行向下取整
- 返回值:向下取整后的整数
- pow() 取幂
- 语法:Math.pow(底数,指数)
- 作用:对数字进行取幂运算
- 返回值:取幂后的结果
- sqrt() 二次方根
- 语法:Math.sqrt(数字)
- 作用:对数字进行二次方跟运算
- 返回值:二次方根后的结果
- abs() 取绝对值
- 语法:Math.abs(数字)
- 作用:对数字进行取绝对值运算
- 返回值:绝对值运算后的结果
- max() 取最大值
- 语法:Math.max(数组)
- 作用:获取若干数字的最大值
- 返回值:其中的最大值
- min() 取最小值
- 语法:Math.min(数组)
- 作用:获取若干数字的最小值
- 返回值:其中的最小值
- PI 近似Π的值
- 语法:Math.PI
- 作用:得到一个近似Π的值
- 返回值:一个近似Π的值
时间常用方法
js的BOM操作
一整套操作浏览器相关内容的属性和方法
- 操作浏览器的历史记录
- 操作浏览器的滚动条
- 操作浏览器页面跳转
- 操作浏览器标签页的开启和关闭
- ……
- 获取浏览器窗口尺寸
- 获取可视窗口宽度
- 获取可视窗口高度
1
2
3
4//获取宽度
window.innerWidth
//获取高度
window.innerHeight
- 浏览器的弹出层
- 提示框
- 询问框
- 输入框
1
2
3
4
5
6//提示框
window.alert('提示信息')
//询问框
window.confirm('提示信息')
//输入框
window.prompt('提示信息')
- 开启和关闭标签页
- 开启
- 关闭
1
2
3
4//开启
window.open('地址')
//关闭
window.close()
- 浏览器常见事件
- 资源加载完成
- 可视尺寸改变
- 滚动条位置改变
1
2
3
4
5
6//加载完成
window.onload = fuction(){}
//可视尺寸改变
window.onresize = fuction(){}
//滚动条位置改变
window.onscorll = fuction(){}
- 浏览器的历史记录操作
- 回退页面
- 前进页面
1
2
3
4//回退页面
window.history.back()
//前进页面
window.history.forward()
- 浏览器卷去的尺寸
- 卷去的高度
1
2document.documentElement.scrollTop
document.body.scrollTop - 卷去的宽度
1
2document.documentElement.scrollLeft
document.body.scrollLeft
- 浏览器滚动到
- window.scrollTo()
- 参数方式
1
2
3
4
5
6
7
8//第一种
window.scrollTo(left,top)
//第二种
window.scrollTo({
left:xx,
top:yy,
behavior:'smooth'
})
- 参数方式
js的定时器
- 间隔定时器
- 按照指定周期(毫秒)去执行执行的代码
1
2
3
4
5
6setinterval(函数,时间)
//函数:要执行的内容
//时间:单位是ms
setinterval(fuction(){
console.log('执行一次')
},1000)
- 按照指定周期(毫秒)去执行执行的代码
- 延时定时器
- 在固定的时间(毫秒)后执行一次指定代码
1
2
3
4
5
6setTimeout(函数,时间)
//时间到达执行的内容
//单位是毫秒
setTimeout(fuction(){
console.log('执行一次')
},1000)
- 在固定的时间(毫秒)后执行一次指定代码
- 定时器的返回值
- 不区分定时器种类
- 表示是是当前页面的第几个定时器
1
2
3
4
5
6
7// 书写第一个定时器
var timer1 = setInterval(function () {}, 1000)
// 书写第二个定时器
var timer2 = setTimeout(function () {}, 1000)
// 输出返回值
console.log( 'timer1 : ', timer1 )
console.log( 'timer2 : ', timer2 )
- 关闭定时器
1
2
3
4
5//语法一
clearInterval(要关闭的定时器返回值)
//语法二
clearTimeout(要关闭的定时器返回值)
//不区分定时器种类
DOM基本操作
定义
一成套操作文档流相关的属性和方法
- 操作元素修改样式
- 操作元素修改属性
- 操作元素改变位置
- 操作元素添加事件
获取元素的方式
确定你要操作的是哪一个元素
- 根据id名称获取
1
2
3
4
5doctument.getElementByld('id名称')
//作用:获取文档流中id名对应的一个元素
//返回值:
//如果有id对应的元素,就是这个元素。
//没有就是null - 根据元素类名获取
1
2
3
4
5document.getElementByClassName('元素类名')
//作用:获取文档流中类名对应的一个元素
//返回值:必然是一个伪数组
//如果有类名对应的元素,有多少获取多少。
//如果没有类名对应的元素,空的伪数组 - 根据元素标签名获取
1
2
3
4
5document.getElementByTagName('标签名')
//作用:获取文档流中标签名对应的一个元素
//返回值:必然是一个伪数组
//如果有标签名对应的元素,有多少获取多少。
//如果没有标签名对应的元素,空的伪数组。 - 根据选择器获取一个
1
2
3
4
5document.querySelector('选择器')
//作用:获取文档流中满足选择器规则的第一个元素
//返回值:
//如果去选择器对应的元素,获取到第一个
//如果没有选择器对应的元素,null - 根据选择器获取一组
1
2
3
4
5document.querySeletorAll('选择器')
//作用:获取文档流中满足选择器规则的所有元素
//返回值:必然是一个伪数组
//如果有选择器对应的元素,有多少获取多少。
//如果没有选择器对应的元素,空的伪数组。
操作元素内容
- 操作文本内容
1
2
3
4//获取
元素.innerText
//设置
元素.innerText = '新内容' - 操作超文本内容
1
2
3
4//获取
元素.innerHTML
//设置
元素.innerHTML = '新内容'
操作元素属性
原生属性
1
2
3
4//获取
元素.属性名
//设置
元素.属性名 = '属性值'自定义属性
1
2
3
4
5
6
7//获取
元素.getAttribute('属性名')
//设置
元素.getAttribute('属性名','属性值')
//删除
元素.removeAttribute('属性名')
//以上方式一般不用于操作元素 类名和样式操作元素类名
1
2
3
4//获取
元素.className
//设置
元素.className = '新类名'操作元素行内样式
1
2
3
4
5//获取
元素.style.样式名
//设置
元素.style.样式名 = '样式值'
//只能获取和设置元素的行内样式获取元素非行内样式
1
2window.getComputedStyle(元素).样式名
//可以获取行内样式,也可以获取非行内样式。
节点操作
- 创建节点
1
2
3document.createElenment('标签名称')
//创建一个指定标签元素
//返回一个创建好的元素节点 - 插入节点
1
2
3
4
5
6
7//语法一
父节点.appendChild(子节点)
//把子节点放在父节点的内部,并且放置在最后的位置
//语法二
父节点.insertBefore(要插入的子节点,哪一个子节点的前面)
//把子节点放在父节点的内部,并且放在指定的某一个子节点前面。 - 删除节点
1
2
3
4
5
6
7//语法一
父节点.removeChild(子节点)
//从父节点删除某一个子节点
//语法二
节点.remove()
//把自己直接删除 - 替换节点
1
2父节点.replaceChild(换上节点,换下节点)
//在父节点内,使用换上节点替换掉换下节点 - 克隆节点
1
2
3节点.conleNode(是否克隆‘后代’替节点)
//把该节点复制一份一摸一样的内容
//返回克隆后的新节点
获取元素尺寸
包括
- 边框boder
- 内边距padding
- 内容content
1
2
3
4
5
6
7
8
9//语法一
元素.offsetHeight
元素.offsetwidth
//获取 元素 内容 + padding + boder 区域的尺寸
//语法二
元素.clientHeight
元素.clientWidth
//获取 元素 内容 + padding 区域的尺寸
事件
前端通过代码的方式和页面中的某个内容做好一个约定
用户触发指定行为的时候,就会执行代码
事件绑定的三要素
- 事件源:
- 和谁做好约定
- 事件类型:
- 约定一个什么行为
- 事件处理函数
- 当用户触发该行为时,执行什么代码
1
事件源.on.事件类型 = 事件处理函数
- 当用户触发该行为时,执行什么代码
事件类型
- 鼠标事件
- click - 鼠标单击
- dbclick - 鼠标双击
- contextmenu - 左键单击
- mousedown - 鼠标按下
- mouseup - 鼠标抬起
- mousemove - 鼠标移动
- mouseover - 鼠标移入
- mouseout - 鼠标移出
- mouseenter - 鼠标移入
- mouseleave - 鼠标移出
- 键盘事件
- keydown - 键盘按下
- keyup - 键盘抬起
- keypress - 键盘键入
- 浏览器事件
- load - 加载完成
- scroll - 滚动
- resize - 尺寸改变
- 触摸事件
- touchstart - 触摸开始
- touchmove - 触摸移动
- touchend - 触摸结束
- 表单事件
- foucs - 聚焦
- blue - 失焦
- change - 改变
- input - 输入
- submit - 提交
- reset - 重置
事件对象
当事件触发时,一个描述该事件信息的对象数据类型
事件对象内的信息
鼠标事件
- offsetX和offsetY
- 相对于触发事件的元素
- client和clientY
- 相对于浏览器可视窗口
- pageX和pageY
- 相对于页面文档流
键盘事件
- 相对于页面文档流
- 键盘编码
事件对象.keyCode
事件传播
浏览器响应事件的机制
- 浏览器窗口最先知道事件的发生
- 捕获阶段:从window按照结构子级的顺序传递到目标
- 目标阶段:准确触发事件的元素接收到行为
- 冒泡阶段:从目标按照结构父级的顺序传递到window
- 本次事件传播结束
阻止事件传播
1 | 事件对象.stopPropagation() |
事件委托
- 利用事件冒泡的机制,把自己的事件委托给结构父级中的某一层
理解面向对象编程
面向对象编程就是通过构建一个能重复调用的函数,完成一种或一系列特定功能。这个函数所实现的功能就叫对象。而思考如何实现这个函数功能,并且编写下来的过程就叫做面向对象编程。
- 实现面向对象编程的主力是自定义构造函数
1
2
3
4
5
6
7var change = function (参数1,参数2,参数3){
this.a(属性) = 参数一
this.b = 参数二
this.c = 参数三
}
var aaa = new change
var bbb = new change - 该函数可以多次调用,用于快速创建新的变量(对象)
- 必须和new连用才能发挥应有的作用
原型
- 作用:由构造函数添加方法,专门给实例对象使用
- 解决问题
- 需要给实例对象内添加方法
- 直接书写在构造函数体内
- 这行为并不好
- 原型是为了解决这个问题的
- 不好的原因
- 把方法书写在构造函数之内
- 每次创建新的实例,都会创建一个函数数据类型
- 多个函数方法,一样,但是占据了多份存储空间
如何优化代码,减少空间占用
构造函数原型
- 每一个构造函数天生自带一个prototype属性,是一个对象数据类型
- 每一个对象天生自带一个__proto__属性,指向所属函数的prototype
- 访问对象成员的时候,首先在自己身上找,自己没有,则去自己的__proto__上找
如何解决问题?
把需要给实例对像添加的方法,放到构造函数的原型prototype上
实例通过自己的__proto__来访问自己所属构造函数的prototype来获取方法,而不用再创建一个新的函数来使用,也就不占用空间内存
1
2
3
4
5
6
7
8
9
10
11
12
13fuction Person(){}
//函数书写完毕,Person.prototype同时出现
Person.prototype.a = 100
//向 Person 的原型中添加成员 a
var s1 = new Person()
//创建一个新的实例对象,它属于构造函数 Person()
// s1.__proto__ === Person.prototype
consloe.log(s1.a)
//访问对象成员的时候,首先在自己身上查找,自己没有,则去自己的__proto__查找,也就是 s1.__proto__.a === Person.prototype.a如果需要多次调用,且有不需要变动的方法或属性的代码,可以放到change函数的原型()中
调用函数change时,如果有没有找到的方法或属性,会去原型里找。
1 | change.prototype.方法名(属性名) = function () { |
原型链
问题
- 实例对象身上的 proto 指向谁 ?
- 指向所属构造函数的 prototype
- s1 所属的构造函数是 Person
- s1.proto 指向 Person.prototype
- Person.prototype 的 proto 指向谁 ?
- Person.prototype 所属的构造函数是谁
- 因为 Perosn.prototype 是一个对象数据类型(Object)
- 在 JS 内所有的 Object 数据类型都是属于 Object 这个内置构造函数
- Person.prototype 是属于 Object 这个内置构造函数的
- Person.prototype 的 proto 指向 Object.prototype
- Person 的 proto 指向谁 ?
=> Person 是一个函数, 函数本身也是一个对象, 就会有 proto
=> 在 JS 内, 所有的函数都是属于内置构造函数 Function 的实例
=> Person.proto 指向 Function.prototype - Object.prototype 的 proto 指向谁 ?
- Object.prototype 是一个对象数据类型, 只要是对象, 都是数据 Object 这个内置构造函数的
- 注意: Object.prototype 在 JS 内叫做顶级原型, 不在有 proto 了
- Object.prototype 的 proto 指向 null
- Object 的 proto 指向谁 ?
- Object 是内一个内置构造函数, 同时也是一个函数, 同时也是一个对象
- 在 JS 内, 所以的函数都是属于内置构造函数 Function 的实例
- Object 也是 Function 的实例
- Object.proto 指向 Function.prototype
- Function.prototype 的 proto 指向谁 ?
- Function.prototype 也是一个对象数据类型
- 只要是对象数据类型都是 Object 的实例
- Function.prototype 的 proto 指向 Object.prototype
- Function 的 proto 指向谁 ?
- Function 也是一个内置构造函数, 也是一个函数
- 在 JS 内, 所有的函数都是属于内置构造函数 Function 的实例
- Function 自己是自己的构造函数
- Function 自己是自己的实例对象
- Function 所属的构造函数的是 Function
原型链
- 用 proto 串联起来的对象链状结构
- 注意: 使用 proto
- 每一个对象数据类型, 都有一个属于自己的原型链
- 作用: 为了访问对象成员
对象访问机制:
- 当你需要访问对象的成员的时候
- 首先在自己身上查找, 如果有直接使用
- 如果没有, 会自动去 proto 上查找
- 如果还没有, 就再去 proto 上查找
- 直到 Object.prototype 都没有, 那么返回 undefined