1. js 的数据类型有哪些?
Undefined ,null,string,boolean,number,object(引用类型);
typeof null 返回object;
symbol 是基本数据类型,每一个symbol值都是一个全局唯一的字符串,你永远不会知道它里面存的什么,symbol值可以作为对象的属性的键。
2.js事件流机制捕获和冒泡
捕获是从上向下,冒泡是从下往上。
3.在HTML中,Location对象的属性都有哪些?
window.location.href:整个URL。
window.location.protocol: 当前URL的协议,包括冒号( :)。
window.location.host:主机,包括冒号(:)和端口(默认80端口和443端口会省略)。
window.location.hostname:主机名,不包括端口。
window.location.port:端口号。
window.location.portname:URL的路径部分,从根路径/开始。
window.location.search:查询字符串部分,从问好?开始。
window.location.hash:片段字符串部分,从#号开始。
window.location.username:域名前面的用户名。
window.location.password:域名前面的密码。
window.location.origin:URL的协议、主机名和端口
4.Math对象的方法使用
Math.Pl//圆周率
min()和max()方法,求一组数中的最小值和最大值
Math.ceil()执行向上舍入,即它总是将数值向上舍入为最接近的整数;
var x=3.98;
var y=Math.ceil(x);//向上取整,不管小数,直接进1
console.log(y);//4
Math.floor()执行向下舍入,即它总是将数值向下舍入为最接近的整数;与parselnt()很像。
var x=3.98;
var y=Math.floor(x);//向下取整,直接省略小数
console.log(y);//3
Math.round()执行标准舍入,即它总是将数值四舍五入为最接近的整数;
var x=3.4;
var y=Math.round(x);
console.log(y);//3
Math.random()方法 返回介于 0 到 1 之间一个随机数,不包括 0 和 1 。(概率上来讲,并不严格。)
var arr=["A","S","D","F","G","H"];
var x=parseInt(Math.random()*arr.length);
console.log(arr[x]);//刷新可以随机出现数组中的字符,
Math.abs()方法 执行绝对值
var x=-12.23;
var y=Math.abs(x);
console.log(y);//,abs绝对值
math对象 其他方法
[图片上传失败...(image-e33892-1637899003388)]
5.substr(m,n)截取一段字符,两个参数m,n,表示从m位开始(不包括m),像后边截取n位;如果只写一个参数m,会从这个参数后边全部截取;
var a = 123456;
console.log(str.substr(0,4))//1234
6.javascript保留字和关键字
关键字26
breakcase catch continue debugger default delete doelsefinally for function
if in instance new return switch this throw try typeofvar voidwhile with
保留字
abstract boolean bytechar class const double enum export extends final float
goto implements import int interface long native package private protected
public short static super synchronized throws transient volatile
在javaScript引擎中使用关键字做标识符会导致"ldentifier Expected" 错误
7.this指向
只用javascript开发的时候,很多开发者多多少少会被this的指向搞蒙圈,但是实际上,关于this的指向,记住最核心的一句话:哪个对象调用函数,函数里面的this指向哪个对象。
1.普通函数:谁调用指向谁
全局变量指向全局对象window
var username = 'cn'
function fn() {
alert(this.username) //cn
}
fu()
有一点需要注意,let 声明的全局变量,不是指向window对象
let username = 'cn'
function fn() {
alert(this.username) //undefined
}
fn()
2.对象函数调用
就是那个函数调用,this指向哪里
window.b = 2222
let obj = {
a: 111,
fn: function() {
alert(this.a) //111
alert(this.b) //undefined
}
}
obj.fn()
3.构造函数中调用
JS里的普通函数可以使用new操作符来创建一个对象,此时该函数就是一个构造函数,箭头函数不能作为构造函数。执行new操作符,其实JS内部完成以下事情:
1.创建一个空的简单Javascript对象(即{});
2.将构造函数的prototype绑定为新对象的原型对象;
3.将步骤1新创建的对象作为this的上下文并执行函数;
4.如果该函数没有返回对象,则返回this。
function A () {
this.a = 1
this.func = () => {
return this
}
}
let obj = new A()
console.log(obj.a) // 1
console.log(obj.func() === obj) // true
4.箭头函数中调用
箭头函数的this指向,和箭头函数定义所在上下文的this相同。对于普通函数,this在函数调用时才确定;而对于箭头函数,this在箭头函数定义时就已经确定了,并且不能再被修改。
let obj = {
A () {
return () => {
return this
}
},
B () {
return function () {
return this
}
}
}
let func = obj.A()
console.log(func() === obj) // true
func = obj.B()
console.log(func() === obj) // false
console.log(func() === window) // true
5.apply、call、bind
在Javascript中,call和apply都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this的指向。举个例子
function fruits() {}
fruits.prototype = {
color: 'red',
say: function() {
console.log('My color is ' + this.color)
}
}
var apple = new fruits()
apple.say() //My color is red
// 但是如果我们有一个对象banana= {color : "yellow"} ,我们不想对它重新定义 say 方法,
//那么我们可以通过 call 或 apply 用 apple 的 say 方法:
banana = {
color: 'yellow'
}
apple.say.call(banana) //My color is yellow
apple.say.apply(banana) //My color is yellow
apply、call 区别
对于 apply、call 二者而言,作用完全一样,只是接受参数的方式不太一样
func.call(this, arg1, arg2)
func.apply(this, [arg1, arg2])
apply、call 实例
// 数组追加
var array1 = [12 , "foo" , {name:"Joe"} , -2458];
var array2 = ["Doe" , 555 , 100];
Array.prototype.push.apply(array1, array2);
// array1 值为 [12 , "foo" , {name:"Joe"} , -2458 , "Doe" , 555 , 100]
// 获取数组中的最大值和最小值
var numbers = [5, 458 , 120 , -215 ];
var maxInNumbers = Math.max.apply(Math, numbers), //458
var maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458
// 验证是否是数组
functionisArray(obj){
return Object.prototype.toString.call(obj) === '[object Array]'
}
bind()
bind()最简单的用法时创建一个函数,使这个函数不论怎么调用都有同样的this值。
bind()方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入bind()方法的第一个参数作为this,传入bind()方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。
this.num = 9
var mymodule = {
num: 81,
getNum: function() {
console.log(this.num)
}
}
mymodule.getNum() // 81
var getNum = mymodule.getNum
getNum() // 9, 因为在这个例子中,"this"指向全局对象
var boundGetNum = getNum.bind(mymodule)
boundGetNum() // 81
当调用bind函数后,bind 函数的第一个参数就是原函数作用域中 this 指向的值
function func() {
console.log(this)
}
let newFunc = func.bind({ a: 1 })
newFunc() // 打印:{a:1}
let newFunc2 = func.bind([1, 2, 3])
newFunc2() // 打印:[1,2,3]
let newFunc3 = func.bind(1)
newFunc3() // 打印:Number:{1}
let newFunc4 = func.bind(undefined / null)
newFunc4() // 打印:window
● 当传入为null 或者 undefined 时,在非严格模式下,this 指向为 window。
● 当传入为简单值时,内部会将简单的值包装成对应类型的对象,数字就调用Number 方法包装;字符串就调用String 方法包装;true/false 就调用Booolean 方法包装。要想取到原始值,可以调用 valueOf 方法。
传递的参数的顺序问题
function func(a, b, c) {
console.log(a, b, c) // 打印传入的实参
}
let newFunc = func.bind({}, 1, 2)
newFunc(3) //1,2,3
// 可以看到,在 bind 中传递的参数要先传入到原函数中。
返回新函数被当成构造函数
// 原函数
function func(name) {
console.log(this) // 打印:通过{name:'wy'}
this.name = name
}
func.prototype.hello = function() {
console.log(this.name)
}
let obj = { a: 1 }
// 调用bind,返回新函数
let newFunc = func.bind(obj)
// 把新函数作为构造函数,创建实例
let o = new newFunc('seven')
console.log(o.hello()) // 打印:'seven'
console.log(obj) // 打印:{a:1}
新函数被当成了构造函数,原函数 func 中的this不再指向传入给 bind 的第一个参数,而是指向用 new 创建实例。在通过实例 O 找原型上的方法 hello 时,能够找到原函数 func 原型上的方法。
apply、call、bind、 比较
● apply、call、bind 三者都是采用改变函数的 this 对象的指向的;
● apply、call、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
● apply、call、bind 三者都可以利用后续参数传参;
● bind是返回对应函数,便于稍后调用;apply、call 则是立即调用。
var obj = {
x: 81
}
var foo = {
getX: function() {
return this.x
}
}
console.log(foo.getX.bind(obj)()) //81
console.log(foo.getX.call(obj)) //81
console.log(foo.getX.apply(obj)) //81
时间格式化函数
function diaplayTime(data) {
//将字符串转换成时间格式
let timePublish = new Date(data);
let timeNow = new Date();
let minute = 1000 * 60;
let hour = minute * 60;
let day = hour * 24;
let month = day * 30;
let year = month * 12;
let diffValue = timeNow - timePublish;
let diffMonth = diffValue / month;
let diffWeek = diffValue / (7 * day);
let diffDay = diffValue / day;
let diffHour = diffValue / hour;
let diffMinute = diffValue / minute;
let diffYear = diffValue / year;
if (diffValue < minute) {
result = "刚刚发表";
} else if (diffYear > 1) {
result = parseInt(diffYear) + "年前";
} else if (diffMonth > 1) {
result = parseInt(diffMonth) + "月前";
} else if (diffWeek > 1) {
result = parseInt(diffWeek) + "周前";
} else if (diffDay > 1) {
result = parseInt(diffDay) + "天前";
} else if (diffHour > 1) {
result = parseInt(diffHour) + "小时前";
} else if (diffMinute > 1) {
result = parseInt(diffMinute) + "分钟前";
} else {
result = "刚刚发表";
}
return result;
}