JS常用知识点
分类:javascript
基本概念
一:JS的输出方法
document.getElementById("").innerHTML=; //id的地方输出
document.write(); //页面输出
console.log(); //控制台输出
alert(); //弹窗输出
二:JS的引入有三种
1、外部引入 <script src="js地址" type="text/javascript" charset="utf-8"></script>
2、内部引入 <script type="text/javascript">js代码</script>
3、行内引入 <body>
<button οnclick="alert(123)">点击我</button>
<!--onclick:点击触发一个事件,alert:弹出一个对话框-->
</body>
三:JS语法(变量):
1、JS是大小写敏感的
2、每条语句结束应该加分号
3、变量必须以字母或_或$开头
4、变量不能是关键字
四:JS命名规范:
1、驼峰法命名 myName 第二个单词首字母大写
五:JS注释:
// //单行注释
/* */ //多行注释
六:JS有七种数据类型:
1、(Number)数字类型:整数 或者是 小数 或者是 科学计数法
例子:1 1.2 12e5
2、(String)字符串类型:带有 双引号 或者 单引号 , 两者没啥区别
例子:"string" 'string'
3、(Boolean)布尔型:值只有 trun 或 false
4、(Object)对象类型:new object{} typeof返回是object对象
5、(Null)类型:null:空 typeof返回是object对象
6、(Undefined)类型:undefined:未定义 typeof返回是object对象
额外引用类型:
(Array)数组类型:new Array[] typeof返回是object对象
(Function)函数类型:function() typeof返回是function对象
ES6新出的:
7、(Symbol)类型:方法let symbol = Symbol(参数) 作用:返回的值是唯一的,可以作为对象的标识符,
例子:(Symbol(1) === Symbol(1)) 输出false
注意:Undefined、Null、Number、Boolean、String 定义为基本数据类型,因为其是按值访问的,可以操作保存在变量中的实际的值。引用类型值是保存在内存中的对象,操作对象时,实际上操作的是对象的引用。
八:JS的运算符:
1、赋值,算术
= + - * /
2、条件,比较
==(先转换类型再比较) ===(直接比较类型和值) < > != <= >=
3、&&(and,两个都为true,才是true)
4、||(或,两个条件一个为true,就是true)
5、!(非,反着来
九:JS循环语句
1、for循环
2、while循环
3、do while循环
4、for in循环遍历数组和对象
5、for of遍历字符)
十一:JS判断条件语句
1、if() else if() else语句
2、switch() case: break default continue语句
3、(条件) ? 真:假三元运算符
4、??空值合并运算符 //值不是null和undefined,就返回该值
数字类型
数字类型的方法
1、Math.floor(num)向下舍入
2、Math.ceil(num)向上舍入
3、Math.round(num)向近舍入
4、num.toFixed(n)将数字后面的小数保留n位
5、isNaN(num)表示是否是非数字
6、parseInt(num)从字符串读取整数
7、parseFloat(num)从字符串读取小数
8、Math.random()随机返回一串0~1小数
9、Math.max(num)从中比较大小,返回最大值
10、Math.min(num)从中比较大小,返回最小值
11、Math.pow(num,次数)返回一个参数多少次幂
数组
从上面的对象我们知道对象允许存储键值集合,这很好,但是我们发现有一些场景对象不是很适合,比如:
当我们想在已有的元素中插入一个新的属性,就很麻烦了
这时候就由数组派上用场了,它能存储有序的集合
声明
创建一个空数组有两种语法:
let arr = new Array();
let arr = [];
绝大多数情况下都是使用第二种声明
let arr = ["Apple", 23, "Plum"];
alert( arr[0] ); // Apple
alert( arr[1] ); // 23
alert( arr[2] ); // Plum
let arr = ["Plum", 23, "Apple"];
alert( arr[0] ); // Plum
alert( arr[1] ); // 23
alert( arr[2] ); // Apple
从上面代码我们可以知道,数组元素是从0开始的,并且跟位置有关,不像对象,属性定位
常用的数组方法
-
arr.push() 描述:从数组尾端添加元素
-
arr.pop() 描述:从数组尾端删除元素
-
arr.unshift() 描述:从数组首部添加元素
-
arr.shift() 描述:从数组首部删除元素
-
arr.concat(...items) 描述:返回一个数组:复制当前数组,并添加items,如果是数组,则取元素
let arr2 = [5, 6];
alert( arr.concat([3, 4]) ); // 1,2,3,4
alert( arr.concat(arr2) ); // 1,2,5,6
-
arr.indexOf(item, from) 描述:从索引 from 开始搜索 item,如果找到则返回索引,否则返回 -1。
-
arr.find(item,index,array) 描述:item是元素,index是查找的条件,array是查找的数组,从array数组查找index,如果返回true,那就返回item
-
arr.findindex() 描述:跟find一样,返回的是元素的索引
-
let results = arr.filter() 描述:跟find差不多,如果找到元素item,则把这元素添加到results中,没找到返回空数组;
-
arr.sort(a,b) 描述:快速排序,注意:这是按照首字排序,在sort()中,2>15,只会按照首字(首字符)比较,如果a>b,返回1,a=b,返回0,a<b,返回-1,则从小到大,反之一样
-
arr.reverse() 描述:返回一个颠倒arr元素中的数组
-
arr.split(',') 描述:可以把逗号作为分隔符,分成一个个数组
let arr = names.split(', ');
for (let name of arr) {
alert( `A message to ${name}.` ); // A message to Bilbo(和其他名字)
}
-
arr.filter() 描述:find 方法搜索的是使函数返回 true 的第一个(单个)元素。
-
arr.slice() 描述:它会返回一个新数组,将所有从索引 start 到 end(不包括 end)的数组项复制到一个新的数组
alert( arr.slice(1, 3) ); // e,s(复制从位置 1 到位置 3 的元素)
alert( arr.slice(-2) ); // s,t(复制从位置 -2 到尾端的元素)
-
arr.splice() 描述:返回删除后的数组,接受三个参数,第一个从第几个开始删除,第二个删除的数量,第三个添加的内容
arr.splice(0, 3, "Let's", "dance");
alert( arr ) // now ["Let's", "dance", "right", "now"]
字符串
字符串的方法
1、str.toUpperCase()转换为大写字母
2、str.toLowerCase()转换为小写字母
3、str.indexOf(查找的参数,从第n个位置开始查找)如果找到就返回索引的位置,否则返回-1
4、str.lastIndexOf()
5、str.includes(查找的参数,开始搜索的位置)有就返回true,没就返回false
6、str.startsWith(查找的参数)查找的参数开头,有就返回true,没就返回false
7、str.endsWith(查找的参数)查找的参数结尾,有就返回true,没就返回false
8、str.splice(start,end,item1...itemN)返回被删除的字符串从start到end部分,并且添加item1...itemN
9、str.slice(start,end)返回字符串从start到end(不包括end)部分
10、str.substring(start,end)返回字符串从start到end(不包括end)部分,运行start大于end值
11、str.substr(start,length)返回字符串从start开始,索取length长度的部分
12、str.trim()删除字符串前后出现的空格
13、str.repeat(n)重复字符串n次
函数
函数就是一个程序,函数可以里面的代码重复调用,不用重复写代码
**有以下几种函数方式**
函数声明
function hello() {
alert( 'Hello everyone!' );
}
hello就是函数名
匿名函数
function () {
alert( 'Hello everyone!' );
}
没有函数名就是匿名函数
匿名函数的四种调用方法
//第一种方法
var a=function(){
console.log("Hello World!");
}
a();
//第二种方法
(function (){
console.log("Hello World!");
})();
//第三种方法
(function (){
console.log("Hello World!");
}());
//第四种方法
[function(){
console.log("Hello World!");
}()];
函数表达式
let hello = function() {
alert( "Hello" );
};
在这里函数被创建,并把里面的值分配给hello。
构造函数
1、它们的命名以大写字母开头。
2、它们只能由 "new" 操作符来执行。
例如:
function User(name) {
this.name = name;
this.isAdmin = false;
}
let user = new User("Jack");
alert(user.name); // Jack
alert(user.isAdmin); // false
嵌套函数
在一个函数内部创建另一个函数,就是嵌套函数
function sayHiBye(firstName, lastName) {
// 辅助嵌套函数使用如下
function getFullName() {
return firstName + " " + lastName;
}
alert( "Hello, " + getFullName() );
alert( "Bye, " + getFullName() );
}
传入多个参数
在JavaScript中,你传入多少个参数,就调用多少个参数,多传入参数是没用的
function sum(a, b) {
return a + b;
}
alert( sum(1, 2, 3, 4, 5) ); //3
从上面代码可以看出,只有两个参数被调用
我们可以使用Rest参数...
就是前面三个点加上数组名称,意思是“将全部参数放在一个数组里”
function sumAll(...args) { // 数组名为 args
let sum = 0;
for (let arg of args) sum += arg;
return sum;
}
alert( sumAll(1) ); // 1
alert( sumAll(1, 2) ); // 3
alert( sumAll(1, 2, 3) ); // 6
当然,我们可以先传入两个参数,再把剩下的参数放进数组中
function sumAll(a, b, ...args) { // 数组名为 args
let sum = 0;
for (let arg of args) sum += arg;
return sum;
}
alert( sumAll(1) ); // 1
alert( sumAll(1, 2) ); // 3
alert( sumAll(1, 2, 3, 4, 5) ); // 15
闭包
“闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭
包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。”
作用域
从闭包中我们知道,正常情况下只能从内部读取外部的变量,无法外部读取内部的变量(其实有方法),这就是函数的作用域
{
// 使用在代码块外不可见的局部变量做一些工作
let message = "Hello"; // 只在此代码块内可见
alert(message); // Hello
}
alert(message); // Error: message is not defined
如何在函数外部读取函数内部的变量?
这是我们经常碰见的情况,我推荐三种方法(更多不止)
第一通过return访问:
function bar(value) {
var testValue = 'inner';
return testValue + value;
}
console.log(bar('fun')); // "innerfun"
return 返回只是变量(testValue + value),还需要调用该函数获取(bar('fun'));
错误的例子:
function bar(value) {
var testValue = 'inner';
}
console.log(bar()); //undefined
虽然成功执行了,但没有返回,所以为undefined
错误的例子
function bar(value) {
var testValue = 'inner';
return testValue;
}
console.log(testValue); //testValue is not defined
需要通过函数来调用,直接调用会报错,因为外部无法读取内部变量
第二通过 闭包 访问函数内部变量:
function bar(value) {
var testValue = 'inner';
var rusult = testValue + value;
function innser() {
return rusult;
};
return innser();
}
console.log(bar('fun')); // "innerfun"
第三立即执行函数:
用它来分离全局作用域,形成一个单独的函数作用域。
<script type="text/javascript">
(function() {
var testValue = 123;
var testFunc = function () { console.log('just test'); };
})();
console.log(window.testValue); // undefined
console.log(window.testFunc); // undefined
</script>
"new Function" 语法
这个创建函数的方法其实用到次数很少,但是很特别,所以后面才写下
语法
let fun = new Function()
特殊点
function getFunc() {
let value = "test";
let func = new Function('alert(value)');
return func;
}
getFunc()(); // error: value is not defined
是不是非常眼熟,咦,这不是上面代码吗,只不过有个new,为什么这样报错了呢?
这就是new Function特殊处,当我们用new Function创建一个函数,那么该函数指向就不是当前的语法环境,而是全局
环境,因此,当我们访问value值,其实该函数访问是全局变量,你可以试试加个全局变量value看看,是不是很特殊?
总结
写完这些,我总结以下观点:
1、函数作用域,内部读取外部变量,外部无法读取内部变量
2、可以传入一个...数组接收全部参数
3、可以通过一些方法读取函数内部变量
从上面例子知道,return等于把变量“导出”,调用该函数等于“引入”,只执行其中一步都不行。
4、new Function指向的是全局环境。
Object
对象
你们可以把对象当成一个抽屉,里面专门放文件,文件写有某个人名字(key),里面的东西(value)
就比如我们创建一个空的对象(抽屉)
let user = new Object(); // “构造函数” 的语法
let user = {}; // “字面量” 的语法
let caomaoHaiZeiTuan = { 一个对象(抽屉)
chuanzhang: "路飞", name就是名字(key),:右边就是对象(value)
age: "22", age就是名字(key),:右边就是对象(value)
jiNeng: "橡胶机关枪",
jingEr: "10亿赏金",
chuanyuan: "索隆", name就是名字(key),:右边就是对象(value)
age2: "18", age就是名字(key),:右边就是对象(value)
jiNeng2: "二刀流",
jingEr2: "8亿赏金",
}
简单来说,对象就是多了一个认证(属性),在草帽海贼团没成立前,以前我们都是喊路飞路飞的,等草帽海贼团成立了,
我们都应该喊,吖,那是草帽海贼团(caomaoHaiZeiTuan)船长(chuanzhang)路飞,年龄(age)22,技能(jiNeng)是橡
胶机关枪,赏金(jingEr)10亿啊哈!原来这样啊,一个对象可以包含多个属性,可以通过不同的属性读取对应的值
对象的引用
let user = { name: "John" };
let lada = user; // 它们是两个数吗?
结果很明显不是,lada只是引用了user的内容
let user = { name: 'John' };
let lada = user;
lada.name = 'hello'; // 通过 "lada" 引用来修改
alert(user.name); // 'hello',修改能通过 "user" 引用看到
还记得基本概念第六题吗?这就是引用类型跟基本类型的区别
如果我们想复制该对象的引用或者完全克隆一个新的对象(不互相引用)该如何实现呢?那可以看下浅拷贝(复制引用)和
深拷贝(完全独立,互不影响)
浅拷贝
三种方法(更多都有)
// 1,新建新对象,复制原来对象的值
let obj = {
name:'AAA',
age:18
}
let obj1 = {
name:obj.name,
age:obj.age
}
obj1.name = 'BBB'
// console.log(obj); // AAA
// console.log(obj1); // BBB
// 2,新建对象,循环添加
let obj2 = {}
for(let key in obj){
obj2[key] = obj[key]
}
obj2.name = 'CCC'
// console.log(obj); // AAA
// console.log(obj2); // CCC
// 3,Object.assign()
let obj3 = Object.assign({},obj) // 第一个参数目标对象要加上
obj3.name = 'DDD'
console.log(obj); // AAA
console.log(obj3); // DDD
深拷贝
三种方法(更多都有)
1. 通过 JSON 对象实现深拷贝
用 JSON.stringify 把对象转换成字符串,再用 JSON.parse 把字符串转换成新的对象,像 function 无法转成
JSON,RegExp 对象也是无法通过这种方式深拷贝。
// 语法--
let deepObj = JSON.parse(JSON.stringify(obj))
// demo--
const obj1 = { a : 1, b : 2}
const obj2 = JSON.parse(JSON.stringify(obj1));
obj1.a = 2;
console.log(obj1); // { a:2, b:2 }
console.log(obj2); // { a:1, b:2 }
对于原对象中undefined、function、symbol 三种数据类型是无效的,因为这三种值会在转换过程中被忽略掉,所以对
有这三种属性的对象使用这种方式会造成上述三种属性的数据丢失。但是对没有这三种属性的数据来说使用这种方式简单
快捷。
2. 通过lodash函数库实现深拷贝
lodash是当前很热门的函数库,提供了 lodash.cloneDeep()可以快速实现对象或数组的深拷贝 loadsh中文网
// 引入loadsh函数库
import _ from 'loadsh'
// 使用cloneDeep实现深拷贝
var obj= [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(obj);
console.log(deep[0] === objects[0]); // => false
3. 使用递归进行深拷贝
function deepClone(source) {
if (!source) return
let target;
if (typeof source === 'object') {
// 根据source类型判断是新建一个数组还是对象
target = Array.isArray(source) ? [] : {}
// 遍历source,并且判断是source的属性才拷贝
for (let key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] !== 'object') {
target[key] = source[key]
} else {
// 如果内部属性存在复杂数据类型,使用递归实现深拷贝
target[key] = deepClone(source[key])
}
}
}
} else {
target = source
}
return target
}
原型
原型、继承、隐式原型、原型链
相信很多人都听说过这些词,但是对这些词不是很明白啥意思
所谓的原型其实指的就是一个prototype属性,每个函数都有一个prototype(原型)属性
隐式原型其实指的就是一个__proto__属性,每个对象都有一个__proto__(隐式原型)属性
继承就是对象的 _proto_属性指向构造函数的 prototype 属性指向的对象
原型链就是对象的 _proto_属性指向构造函数的 prototype 属性的链条
从图片我们可以知道,其实_proto就是指向上级,prototype指向就是自身
function Outer() {
name: "张三"
}
let animal = {
eats: true
};
let rabbit = {
jumps: true
};
Outer.prototype //{constructor: ƒ}
指向Outer,每个函数都有一个原型
Outer._proto_ //ƒ () { [native code] }
rabbit.__proto__ = animal;
rabbit.eats //eats: true
rabbit.prototype = animal;
rabbit.eats //undefined
animal.jumps //undefined
我们可以看到,rabbit.__proto__ = animal,rabbit.eats=true,可以看出rabbit继承了animal的方法,而
animal无法使用,当我们再用rabbit.prototype = animal,却发现rabbit无法继承animal方法,所以我们知
道,隐式原型其实可以继承方法
rabbit.prototype //undefined
类型识别有哪些方法
分别是:1. typeof 2. Object.prototype.toString 3. constructor 4. instanceof
- typeof
它返回值是一个字符串,该字符串说明运算数的类型。typeof一般只能返回如下几个结果:
number,boolean,string,function,object,undefined
console.log(typeof 'abc'); //string
console.log(typeof 1 ); //number
console.log(typeof true ); //boolean
console.log(typeof undefined ); //undefined
console.log(typeof null ); //object
console.log(typeof {name: 'moon'} ); //object
console.log(typeof function () {} ); //function
console.log(typeof [] ); //object
console.log(typeof new Date() ); //object
console.log(typeof /\d/ ); //object
function Person() {}
console.log(typeof new Person() ); //object
只能识别原始类型(null除外),不能识别对象类型
- Object.prototype.toString
它可以很严谨的识别原始类型和对象类型
//先把方法封装成一个函数
function type(obj) {
return Object.prototype.toString.call(obj).slice(8,-1);
}
//字符串截取我们需要的部分
console.log(type('moon')); //String
console.log(type(1)); //Number
console.log(type(true)); //Boolean
console.log(type(undefined)); //Undefined
console.log(type(null)); //Null
console.log(type({})); //Object
console.log(type([])); //Array
console.log(type(new Date())); //Date
console.log(type(/\d/)); //RegExp
console.log(type(function () {})); //Function
function Person() {
}
console.log(type(new Person())); //Object
- constructor
查看对象的构造函数
4.instanceof
判断对象和构造函数之间的关系
//能够判别内置对象
var a=new Array();
console.log(a instanceof Array); //true
console.log(a instanceof Object);//true.(因为Array是object的子类)
//能够判别自定义对象类型
function test(){};
var a=new test();
console.log(a instanceof test); //true
//不能判别原始数据类型
console.log(1 instanceof Number); //false
console.log('moon' instanceof String); //false
this
this算是最常用最重要之一了,新手对this是非常容易感到困惑的,
ES5中,其实你只要记得一句话:**谁调用this,this就指向谁**,记住这句话,再加上我下面的使用场景,理解是毫无
问题的。
场景1:全局环境中的this指向就是全局对象
var name = '吃饭';
function a(){
var name = '睡觉';
console.log(this.name);//吃饭
console.log("this指向:" + this) //this指向:Window
}
a();
新手肯定对这个结果感到意外,明明this.name离"睡觉"更近啊,不应该指向"睡觉"吗,还记的我刚刚开始说的那句话吗
?**谁调用this,this就指向谁**,当我们执行a()发现,咦,a()前面没有东西调用啊,就是指向"睡觉"才对啊,其实
不是,前面没有调用的对
象的话,那么就是全局对象Window调用,Window.a(),注意:这不能在严格模式,否则为undefined
场景2:对象内部函数的this指向调用函数的当前对象
var name = "吃饭";
var a = {
name: "睡觉",
test : function () {
console.log(this.name); // 睡觉
}
}
a.test()
相信有上一个场景大家对这个答案应该没什么疑惑了吧,我们可以看到test函数是由a调用的,所以this指向a的值
我改动一下代码,看看这个例子
var name = "吃饭";
var a = {
name: "睡觉",
test : function () {
console.log(this.name); // 睡觉
}
}
window.a.test()
还是刚刚那句话“谁调用this,this就指向谁”,最后调用它的对象仍然是对象a。
场景3:匿名函数中的this指向全局对象
var name = "吃饭";
var a = {
name: "睡觉",
test : (function () {
console.log(this.name); // 吃饭
})()
}
a.test()
因为匿名函数是一个没有指针的全局变量,那么它的指向的就是全局 就是window对象,所以最后是window调用,所以还
是刚刚那句话“谁调用this,this就指向谁”
场景4:setInterval和setTimeout定时器中的this指向全局对象
var name = "吃饭";
var a = {
name : "睡觉",
func1: function () {
setTimeout( function() {
console.log(this.name)
},100);
}
};
a.func1()
大家看看跟上一个匿名函数有啥区别,聪明的你肯定发现了,setTimeout执行也是一个匿名函数
看看setInterval的
var name = "吃饭";
var a = {
name : "睡觉",
func1: function () {
setInterval( function() {
console.log(this.name)
clearInterval(a)
},100);
}
};
a.func1()
场景5:构造函数中的this指向构造出的新对象
var name = "吃饭"
function Person(name,age){
this.name = name;
this.sayName = function(){
console.log(this.name);
}
}
var a = new Person('睡觉');
a.sayName();
构造函数中的this指向构造出的新对象,new Person()其实已经是调用了这个函数
场景六:new Function中的this指向全局对象
var name = "吃饭"
function Foo(){
name : "睡觉"
this.bar = function(){
var f = new Function("alert(this.name)");
f();//[object Window]
}
}
var foo = new Foo();
foo.bar(); //吃饭
这个例子看完可能有点懵,还是那句话“谁调用this,this就指向谁”,当我们删除f()发现得出undefined,也就是说其
实是f()调用了this,而f()没有自已的name,所以它的指向是全局对象的name。
ES6的箭头函数
前面的场景其实都是ES5的,现在看看特殊的ES6箭头函数的this,箭头函数需要记得这句话:“箭头函数中没有 this
绑定,必须通
过查找作用域链来决定其值,如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this,否则
,this 为
undefined”,太长不理解没事,看看下面代码再来理解这句话
套用一下场景4的代码
var name = "吃饭";
var a = {
name : "睡觉",
func1: function () {
setTimeout( () => {
console.log(this.name)
},100);
}
};
a.func1() //睡觉
跟场景4不一样对不对,其实这里我们就可以看出,箭头函数的this其实是从内往外找的,我们再读读那句话,是不是瞬
间又理解了点再看看这个例子:
var name = "吃饭";
var a = {
name : "睡觉",
func1: function () {
console.log(this.name)
},
func2: function () {
setTimeout( () => {
this.func1()
},100);
}
};
a.func2() //睡觉
改变this的三种方法
使用 apply、call、bind 函数也是可以改变 this 的指向的
apply
var name = "吃饭";
var a = {
name: "睡觉",
test : function(){
console.log(this.name);
}
};
a.test() //睡觉
a.test.apply() //吃饭
a.test.apply(a) //睡觉
眼熟吧朋友们,这其实是场景2的代码,区别就是多了一个apply(),结果就变成了吃饭,三种结果,我相信你已经明白
apply是如何改变this了,没错,就是apply(this)
call
var name = "吃饭";
var a = {
name: "睡觉",
test : function(){
console.log(this.name);
}
};
a.test() //睡觉
a.test.call() //吃饭
a.test.call(a) //睡觉
眼熟吧,跟上面一模一样,其实它们区别只是传入的参数不一样,下面再说哦
bind
var name = "吃饭";
var a = {
name: "睡觉",
test : function(){
console.log(this.name);
}
};
a.test() //睡觉
a.test.bind()
a.test.bind(a)
你会发现除了第一个执行了,其他都没有执行,这就是bind特殊点,你需要再**抽它一下**
a.test.bind()() //吃饭
a.test.bind(a)() //睡觉
又出现了,很明显,bind需要你再执行它一次才行
apply、call、bind区别
从上面我们清楚了如何利用apply、call、bind改变this了,现在我们要了解它们之间的区别了
apply和call区别
其实 apply 和 call 基本类似,他们的区别只是传入的参数不同。
apply 和 call 的区别是 call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组。
var name = "吃饭";
var a = {
name: "睡觉",
test : function(a,b){
console.log(this.name + a + b);
}
};
a.test.apply(a,["打游戏","上厕所"]) //睡觉打游戏上厕所
var name = "吃饭";
var a = {
name: "睡觉",
test : function(a,b){
console.log(this.name + a + b);
}
};
a.test.call(a,"打游戏","上厕所") //睡觉打游戏上厕所
一不小心爱好都写出来了,我们可以从这两个例子充分了解到apply和call区别了吧
call和bind区别
细心的同学可能已经发现call和bind的区别了,废话不多说,上代码
var name = "吃饭";
var a = {
name: "睡觉",
test : function(a,b){
console.log(this.name + a + b);
}
};
a.test.call(a,"打游戏","上厕所") //睡觉打游戏上厕所
var name = "吃饭";
var a = {
name: "睡觉",
test : function(a,b){
console.log(this.name + a + b);
}
};
a.test.bind(a,"打游戏","上厕所")() //睡觉打游戏上厕所
对,没错,区别在于你要再执行一次
最后感言一下:这是本人第一张文章,本人也只是学习半年多前端的菜鸟,里面要是有啥不对可以指正下,大家相互学习进步,这里只是讲一下JS的常用,还有很多没写到,以后本人会陆陆续续写下ES6、Vue等等看看能不能组成一个系列,我会把我这半年多所学的东西一步一步写上去,给自已知识来个保存。觉得可以的小伙伴就点个赞吧!写的真累,因为每个代码我都要验证,毕竟我也是菜鸟,不能误导别人
