答:同源策略是为了保证用户信息安全,是浏览器的机制,防止恶意的网站窃取别人的数据,只允许访问来自同一个站点的资源 同源是指:协议相同,域名相同,端口相同。这三者相同就是同源。如果不同源,浏览器就会作出限制。
开发android或ios有跨域问题吗? 答:没有
使用RN或flutter开发原生APP,有跨域问题? 答:没有
JSONP不是ajax发送的请求,是script标签的src发送的请求。 jsonp原理.js
// JSONP原理 function jsonp(options){ // 1)产生一个函数名(函数名随机) let callBackName = 'wancai'+Math.random().toString().substr(2) + Math.random().toString().substr(2); // 2)定义函数 全局函数 window[callBackName] = function(params){ if (params !== null){ options.success(params) }else{ options.failure(params) } // 2-1) 删除之前创建的scripte标签 scriptE.remove(); // 2-2) 把创建的全局函数设置为null window[callBackName] = null; } // 3)取出url地址 let jonspUrl; if(options.data !== undefined){ jonspUrl = options.url + "?" + options.data + "&callBack="+callBackName }else{ jonspUrl = options.url + "?callBack="+callBackName } // 4)创建一个script标签 let scriptE = document.createElement("script"); scriptE.src = jonspUrl document.body.appendChild(scriptE) } let btn = document.getElementById("btn"); btn.addEventListener("click",()=>{ /* // 第1步:创建一个xhr对象 let xhr = new XMLHttpRequest(); // 第2步:设置连接 xhr.open("get","http://localhost:3000/api/v1") // 第4步:监听xhr状态变化 if(xhr.onreadystatechange == 4 && xhr.status == 200){ console.log(xhr.responseText) } // 第3步:发出请求 xhr.send(null)*/ // 使用JSONP发出请求 jsonp({ url:"http://localhost:3000/api/v1", data:"a=1&b=2", success:function (data) { console.log(data) }, failure:function (data) { console.log("数据请求失败") } }) })server.js
let express = require("express"); let app = express(); app.get("/api/v1",(req,res)=>{ /* console.log(`${req.query.callBack}(${ JSON.stringify({ "name":"wangcai", "age":100 }) })`);*/ res.send(`${req.query.callBack}(${ JSON.stringify({ "name":"wangcai", "age":100 }) })`) }) app.listen(3000,()=>{ console.log("server is running on 3000~") })index.html
<button id="btn">发送JSONP请求</button> <script src="./jsonp原理.js"></script>基本使用:
function fn(num1,num2) { console.log(this) return num1+num2; } fn(); // => window fn.call(); // => window // 1)改变this指向 2)让fn执行 let obj = {name:"wc"} console.log(fn.call(obj,1,2)) // => {name: "wc"} // call也可以传递参数定义一个函数,函数也是对象,对象就可以 .call ,如果不传递参数或直接调用,函数中的this指向window;传递的第一个参数是obj,函数中的this就指向obj。
模拟call
<script> ;(function(){ //context是obj function mycall(context){ context = context ? Object(context) : window; // g调用了mycall,mycall中this指g,所以这个this代表g函数 //context.f表示obj打点调用g函数,所以g函数中的this指向obj context.f = this; let args = []; for(let i = 1; i<arguments.length; i++){ args.push(arguments[i]) } let res = context.f(...args); delete context.f; return res; } //每个函数对象上都挂一个mycall方法 Function.prototype.mycall = mycall; }()) function g(a,b) { console.log(this); return a+b; } let obj = {name:"wc"} let r = g.mycall(obj,6,6); console.log(r) </script>apply和call的区别: 仅仅是传参的区别,作用一样。apply有参数时,以数组的形式进行传递。
<script> ;(function () { function myapply(context,args) { context = context ? Object(context) : window; context.gn = this; if(!args){ return context.gn(); } let res = context.gn(...args) delete context.gn; return res; } Function.prototype.myapply = myapply; }()) // 模拟apply的实现 function fn(num1,num2) { console.log(this) return num1 + num2; } console.log( fn.apply()) let obj = {name:"wc"} console.log(fn.myapply(obj)) console.log(fn.myapply(obj,[1,2])) </script>call、apply、bind 三者都是用于改变函数体内this的指向,但是bind与apply和call的最大的区别是:bind不会立即调用,而是返回一个新函数,称为绑定函数,其内的this指向为创建它时传入bind的第一个参数,而传入bind的第二个及以后的参数作为原函数的参数来调用原函数。
bind:
改变this指向bind前面的函数不执行返回一个绑定this之后的函数bind的使用
<script> function fn(num1, num2) { console.log(this) console.log(num1 + num2) return num1 + num2; } let obj = { name: "wc" } let gn = fn.bind(obj, 1, 2) console.log(gn); //函数fn gn(); //结果:{name:"wc} 3 console.log(gn()); //结果:{name:"wc} 3 3 </script> <script> function fn(num1, num2) { console.log(this) console.log(num1 + num2) return num1 + num2; } let obj = { name: "wc" } let gn = fn.bind(obj) gn(4,5) //结果 {name:"wc} 9 console.log(gn(4,5)); //结果:{name:"wc} 9 9 </script> let obj = { name:"wc" } let gn = fn.bind(obj,6); console.log(gn(8)); 结果 //结果:{name:"wc} 14 14 分别传给num1和num2,相当于传了[1,2] let obj = { name:"wc" } let gn = fn.bind(obj,6,6); console.log(gn(8,8)); 结果 //结果:{name:"wc} 12 12 相当于传了[6,6,8,8]bind的原理
<script> ;(function () { function mybind(context) { // arguments是伪数组 可以转成数组(slice,1,删除数组的第一个元素) let bindArgs = Array.prototype.slice.call(arguments,1); // this指的是下面的fn函数 that指fn let that = this; function xxx() { //args表示可能是在调用gn函数时的传参 let args = Array.prototype.slice.call(arguments); // this 指window 因为下面是window调用的 //concat 连接数组 return that.apply(context, bindArgs.concat(args)) // [1,3] } return xxx; //需要返回一个函数 } Function.prototype.mybind = mybind; }()) function fn(num1,num2) { console.log(this) console.log(num1+num2) return num1+num2; } let obj = { name:"wc" } let gn = fn.mybind(obj,1,2) console.log(gn()) </script> <script> ;(function () { function mybind(context){ let bindArgs = Array.prototype.slice.call(arguments,1) // this就是fn let that = this; function Mn() {} function xxx() { // console.log(this) 这个this和下面new出的函数o指向一个队形 let args = Array.prototype.slice.call(arguments) //如果this是xxx构造器构造的,就说明new了,就让fn中this指向new创建的 return that.apply(this instanceof xxx ? this : context,bindArgs.concat(args)) } // xxx.prototype = this.prototype; // 相当于改变xxx的原型会影响 fn的原型 Mn.prototype = this.prototype; xxx.prototype = new Mn(); xxx.prototype.m2 = 666; return xxx; } Function.prototype.mybind = mybind; }()) function fn(a,b) { console.log(this) console.log(a+b) return a+b; } fn.prototype.m1 = 888; let obj = {name:"wc"} let gn = fn.mybind(obj,1) // console.log(gn(2)); let o = new gn(2); console.log(o.m1) console.log(fn.prototype.m2) </script>内部创建一个对象 让this指向这个对象 返回这个对象
<script> function Dog(name) { // 内部创建一个对象 让this指向这个对象 返回这个对象 this.name = name; // 私有属性 // return 123; // 返回基本数据类型没有任何含义 /*return { age:100 }*/ } Dog.prototype.say = function(){ // 公有属性 console.log("say...") } let wc = new Dog("wangcai") console.log(wc) console.log(wc.name) console.log(wc.say()) </script>new是运算符,运算符只能使用函数来模拟
<script> // 模拟new的实现 问:new是什么? 答:运算符 现在要模拟运算符 // 运算符只能使用函数来模拟 function myNew() { //context等于Dog,shift会删除第一个并返回 // let context = Array.prototype.shift.call(arguments) let context = [].shift.call(arguments) let newObj = {}; newObj.__proto__ = context.prototype let r = context.apply(newObj,arguments) return r instanceof Object ? r : newObj; } function Dog(name) { this.name = name; } Dog.prototype.say = function(){ // 公有属性 console.log("say...") } // let wc = new Dog("wangcai",1,2,3) let wc = myNew(Dog,"wangcai",1,2,3) console.log(wc) console.log(wc.name) console.log(wc.say()) </script>