知识点补充 toString toFixed call apply

(1)toString

我们以前讲过,说 undefined 和 null 不能调用 toString,会报错的,现在我们就知道原因了:数字能调用 toString 是因为数字可以调用包装类,包装成对象然后一层一层 往上访问一直到终端 Object.prototype,所以数字是肯定有 toString 的,但是 undefined 和 null 是没有包装类的,他就是一个原始值,他也没有原型,所以他俩不可能有 toString。现在我们就来研究一下 toString
我们访问 true.toString()就得到“true”,我们访问 123.toString()就会报错,因为他会认为这个数字是浮点型的,是小数点,小数点后必须跟数字啊,跟字母肯定不行, 所以会报错,我们 var num = 123;然后访问 num.toString()得到“123”,但是我们 var obj = {};然后访问 obj.toString()得到"[object Object]",这是为啥?不是应该返回字符串的大括号吗?
其实上边的 obj.toString()他毋庸置疑拿的就是 Object.prototype 里的 toString,但是你 var num = 123,然后 num.toString(),他就会隐式的经过包装类 new Number(num).toString(),这里的原型就是 Number.prototype,Number.prototype 的原型才是 Object.prototype,但是在 Number.prototype 里就有这个 toString 方法,即 Number.prototype.toString = function(){…},这就形成了一个原型链,那么假如说 Number 上有这个 toString 方法的话我就不用你 Object 上的了,然而 Number 上正好有这个方法,所以 Number 调用的 toString 是自己重写过的,原型上有这个方法,我又写了一个同一个名字不同功能的方法叫做重写。比如说:

Person.prototype = {
	toString : function(){
		return "hehe";
	}
}
function Person(){
}
var person = new Person();

我们假如 Person.prototype 里边不写东西的话,调用 person.toString()他就会拿到 Object.prototype 里的 toString,输出"[object Object]",但是我们在近处写一个 toString,这时候你再访问 person.toString 就得到“hehe”,因为我们在近处截断了。 这种和原型链上名字一样的方法但实现不同功能的就叫方法的重写,重写就是覆盖。
其实系统内部把 Number、Array、Boolean、String 这些里的原型 prototype 都把 toString 重写了,所以 var num = 123,访问 num.toString()就是‘123’.因为 Object.prototype 里的 toString 没有啥用,所以他的后代子孙都重写了这个方法。 注意:我们之前讲的 document.write 不能算是真正意义上的打印,他会调用 toString 方法,然后给你返回,虽然你 var num =123;document.write(num)可以打印 123, 但是比如你 var obj = {},在 document.write(obj)就是[object Object],var obj=Object.create(null),在 document.write(obj)就会报错,因为你没有原型就 没有 toString 方法,所以 document.write 不是真正的输出方法,我们一般用 console.log。

(2)toFixed

这里讲一个小bug哈,比如说我们在控制台访问0.14*100就得到14.000000000000002, 这是一个无法解决的 bug,是因为 js 精度不准,数据会发生一小点的偏差,所以要尽量避免小数操作,即使有小数操作,也要借用两个工具: 向上取整:例如 Math.ceil(123.234)得到 124,向上取整 0.1 他也会认为是 1 向下取整:例如 Math.floor(123.999)得到 123,不管后边有多少位小数,都把他们割掉。
产生随机数:Math.random(),调用一次产生一个随机数,0-1 中间的随机小数,两边不会到头。比如说:

for(var i = 0; i<10; i++){
	var num = Math.floor(Math.random() * 100);
	console.log(num);
}

我们不保留有效数字位了,直接乘以 100 然后取整即可。
考点:js 可正常计算的范围:小数点前 16 位,后 16 位,有科学计数法的除外,比如 0.000000000000000001 + 0.000000000000000001 就得 2e-18(2 乘以 10 的-18 次方)。 但是你 0.10000000000000001 + 0.000000000000000001 他就输出 0.1。

(3)call 和 apply

call 和 apply 都是更改 this 指向的

①:call

比如说:

function test(){
}
test();

任何一个方法都可以.call,其实方法的执行就是方法.call 执行,例如上边的,test() 就相当于 this.call(),call 还有一个更高深的用法:

function Person(name,age){
	this.name = name;
	this.age = age;
}
var obj = {};
Person.call(obj);

call 后边的括号里是可以传东西的,比如传一个 obj 进去,他就会引导着 Person 发生很大的变化。我们在以前讲到如果在 Person 底下 new 的话,this 就代表了构造函数所产生的对象,我们假如说没有 new 的话,this 默认是指向 window 的,但是我们在 call 里传 obj 了,那么这个 this 就不是默认的了,就变成 obj 了,就是 call 里边传谁进去,this 就是谁。等于说里边现在执行的时候就是 obj.name = name,obj.age = age, 即使是这样,依然可以传参:

Person.call(obj,'cheng',300);

现在访问obj就得到{name: “cheng”, age: 300},因为call括号里的第一位会改变this 指向,第一位以后都会当成正常的实参传到形参里边去,所以这里边第二个实参对应的是函数执行的第一位形参,第三个实参对应的是函数执行的第二位形参。所以 call 的根本原因是改变 this 指向,借用 Person 的执行封装了 obj,借用你的方法来实现我 的功能。

应用:我们在开发的时候讲究的是快准狠,首先,快,同事之间开发,你写的方法可以实现我的功能,那我就不用写了。

例:

function Person(name,age,sex){
	this.name = name;
	this.age = age;
	this.sex = sex;
}
function Student(name,age,sex,tel,grade){
	Person.call(this,name,age,sex);
	this.tel = tel;
	this.grade = grade;
}
var student = new Student("sunny",123,"male",139,2017);

解析:这是一个非常好的例子,这个 call 的作用只有一个,就是改变 this 指向,那 么就倒出来借用别人的函数来实现自己的功能,你 Person.call()他就一定会执行 Person,然而里边传了一个 this,我们在外边 new 了,那么这个 this 就代表 student, 我们再来看 Student 这个函数,预编译第三步的时候实参和形参就相互统一了,而预编译发生在函数执行的前一刻,等于说执行第一句 Person.call(this,name,age,sex); 的时候 Student 里的形参已经有值了,所以第一句 call 括号里拿的是 Student 传好的形参,是具体的值,然后在把他作为实参传到 Person 里,然后利用 Person 的方法实现了自己的一个封装,其实 call 写在那里就相当于把 Person 里边的三条语句拿到 Student 里了。封装后 student 里就有 name、age 和 sex 了,再执行自己的两行,加上 tel和grade。完事后我们访问student就得到Student{name: “sunny”, age: 123, sex: “male”, tel: 139, grade: 2017}。但是这里你自己的需求必须完全涵盖人家的需求, 比如说你不想用 sex 那是不行的,你用 call 了,那么这三条语句一定会走下来。

②:apply

call 和 apply 基本上是一样的,只是写法不一样,call 需要把实参一个个传进去,但是 apply 只能传一个值 arguments,即实参列表:

function Person(name,age,sex){
	this.name = name;
	this.age = age;
	this.sex = sex;
}
function Student(name,age,sex,tel,grade){
	Person.apply(this,[name,age,sex]);
	this.tel = tel;
	this.grade = grade;
}
var student = new Student("sunny","123","male",139,2017);

其实非常简单,arguments 是数组,那么就直接加一个[ ]就行了,但是记住 this 不能加在里边。

考点: call 和 apply 的作用和区别:他俩都是改变 this 指向,区别传参列表不同。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
object.prototype.toString.call/apply() 是 JavaScript 中的方法,用于获取一个对象的类型信息。 在 JavaScript 中,每个对象都有一个 toString() 方法,用于将对象转换为字符串。object.prototype.toString.call() 和 object.prototype.toString.apply() 都可以用于调用对象的 toString() 方法。但是由于 toString() 方法是对象原型的方法,不是直接继承的,因此需要通过 call() 或 apply() 来指定 this 对象。 调用 object.prototype.toString.call(obj) 或 object.prototype.toString.apply(obj) 的结果将返回 obj 对象的类型信息。这个类型信息是一个包含对象的类型的字符串,在大多数情况下表示对象的内部 [[Class]] 属性的值。 这个类型信息通常以 "[object 类型]" 的形式返回,其中类型可以是以下之一: - "[object String]" 表示 obj 是一个字符串。 - "[object Number]" 表示 obj 是一个数字。 - "[object Boolean]" 表示 obj 是一个布尔值。 - "[object Undefined]" 表示 obj 是 undefined。 - "[object Null]" 表示 obj 是 null。 - "[object Object]" 表示 obj 是一个普通的对象。 - "[object Array]" 表示 obj 是一个数组对象。 - "[object Function]" 表示 obj 是一个函数对象。 通过调用 object.prototype.toString.call/apply() 方法,我们可以更准确地判断一个对象的类型,避免了 typeof 操作符的局限性。例如,使用 object.prototype.toString.call([]) 返回的结果为 "[object Array]",可以确定该对象是一个数组。 总之,object.prototype.toString.call/apply() 是一种用于获取对象类型的常用方法,用于更准确地判断对象的类型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山大王杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值